home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / other / robodoc3.0j / source / robodoc.c < prev    next >
Text File  |  1998-01-05  |  91KB  |  3,058 lines

  1. /****h* Autodoc/RoboDoc.c [3.0j]
  2.  * NAME
  3.  *   RoboDoc.c -- AutoDoc formatter
  4.  * COPYRIGHT
  5.  *   (c) 1994-1997  Maverick Software Development
  6.  *   This software is public domain and can be freely redistributed as
  7.  *   long as it is in its original state.
  8.  * FUNCTION
  9.  *   RoboDoc.c is intended to be a replacement for the original AutoDocs
  10.  *   program.  RoboDoc.c will extract the procedure comment headers
  11.  *   from a source file, and put them into a separate documentation file.
  12.  *   There are five different file output formats:
  13.  *       ASCII
  14.  *       HTML (HyperText Markup Langauge) -- mainly used on the Internet;
  15.  *           thus the files can be viewed with a normal HTML viewer/browser
  16.  *       AmigaGuide -- this format can be viewed by AmigaGuide (Amiga only)
  17.  *       LaTeX - as input to LaTeX to produce .dvi files
  18.  *       RTF (Rich Text Format) -- as input to the Help compiler (Windows only)
  19.  * AUTHOR
  20.  *   Frans Slothouber:  <slothoub@xs4all.nl>.
  21.  *     Source code and additional extensions
  22.  *     from version 2.0 and up.
  23.  *
  24.  *   Jacco van Weert: <weertj@IAehv.nl>
  25.  *     Original idea and program.
  26.  *
  27.  *   Bernd Koesling:  <KOESSI@CHESSY.aworld.de>
  28.  *     Bug fixes, functional improvements, code cleanup.
  29.  *
  30.  *   Anthon Pang:  <apang@mindlink.net>
  31.  *     RTF support, Bug fixes.
  32.  *
  33.  *   Thomas Aglassinger: <agi@sbox.tu-graz.ac.at>
  34.  *     Fixes and cleanup of HTML-output
  35.  *
  36.  * CREATION DATE
  37.  *   20-Dec-94
  38.  * MODIFICATION HISTORY
  39.  *   Modifications by Jacco van Weert.
  40.  *     19-Jan-95     -  v0.8:   First test beta-version
  41.  *     26-Jan-95     -  v0.92:  2nd test beta-version
  42.  *     2-Feb-95      -  v0.93:  Mungwall hit, solved.
  43.  *                              When item headers, are also available
  44.  *                              in body then parts are duplicated solved.
  45.  *     Mar-95        -  v1.0a:  Final version
  46.  *     2-Apr-95      -  v1.0b:  Bug fixes
  47.  *                              Procedure header search bug solved.
  48.  *                              Print 'created procedure' text
  49.  *     20-Apr-95     -  v1.1a:  INTERNALONLY option added.
  50.  *                              Sort problem solved.
  51.  *   Modifications by FNC Slothouber.
  52.  *     10-May-1995 -  v2.0a  * Program completely rewritten
  53.  *                           * added SOURCE item and LaTeX output.
  54.  *                           * added TAB converter.
  55.  *     11-May-1995 -  v2.0b  * Accepts headers that start with
  56.  *                             any sequence of non-spaces.
  57.  *                             RoboDoc should work with any
  58.  *                             type of programming language now.
  59.  *     12-May-1995 -  v2.0c  * Bug fixes.
  60.  *     15-May-1995 -  v2.0d  * New Defaults file.
  61.  *                           * Added Verbose option.
  62.  *     24-May-1995 -  v2.0e  * Fixed a bug that cause the
  63.  *                             CleanUp Routine to lock up.
  64.  *                           * Improved the HTML output,
  65.  *                             should work faster now.
  66.  *   Modifications by Koessi
  67.  *     01-Aug-1995  - v2.0?  * more robust parsing, less enforcer-hits
  68.  *                           * removed self-referencing links !
  69.  *                           * remarked most changes with *koessi*
  70.  *                           * added GoldEd-foldmarks
  71.  *                           * compiled successfully with SAS-C 6.3
  72.  *     07-Aug-1995   -       * automated foldmarks "\***"
  73.  *                           ! GoldEd's foldmarks == RoboDoc marker !
  74.  *                           * quoted source parsing enhanced
  75.  *     08-Aug-1995   -       * a lot of while instead of for
  76.  *                           * a lot of switch() instead of ifelse
  77.  *                           * version defined
  78.  *                           * RB_Say, RB_Panic now useable like printf()
  79.  *                             new formats for nearly all output-strings
  80.  *                           * char *whoami is global copy of argv[0]
  81.  *                           * BOLD <- MAKE_LARGE && AMIGAGUIDE
  82.  *                           * succesfully compiled&tested on HPUX
  83.  *                           (HP9000/800)
  84.  *                           * optimized listfunctions
  85.  *                           * encapsulated header- and link-
  86.  *                             allocating and freeing
  87.  *                           * RB_Find_Function_Name() replaced
  88.  *                             with RB_FilePart()
  89.  *  Modifications by FNC Slothouber.
  90.  *    18-Aug-1995   -  v3.0  * New scanner that searches for
  91.  *                             a set default markers that define
  92.  *                             what is a comment or what is not
  93.  *                             and that define what or what is not
  94.  *                             a header/end marker.
  95.  *                           * Added Beast Support
  96.  *    27-Aug-1995   - v3.0b  * Fixed a bug with the defaults file
  97.  *                           * Improved search algorithm
  98.  *                             RoboDoc is now 5.8 times faster.
  99.  *    06-Sep-1995   - v3.0c  * Bug fixes
  100.  *    08-Oct-1995   - v3.0d  * Bug fixes
  101.  *    04-Feb-1996   - v3.0e  * fixed the problem with the TOC
  102.  *                             that included links to headers that
  103.  *                             were not selected. (i.e internal)
  104.  *    Modifications by apang
  105.  *    08-Mar-1996   - v3.0f  * Cleaner build for Borland C++ 4.52
  106.  *                           * Added more markers (C++, Pascal, Modula-2, COBOL)
  107.  *                           * Added more item types/names
  108.  *                           * Added #defines for the preamble (COMMENT_ROBODOC
  109.  *                             and COMMENT_COPYRIGHT)
  110.  *                           * BLANK_HEADER for detection of asterisk'd lines
  111.  *                           * RB_Say() the GENERIC header warning instead of
  112.  *                             using printf()
  113.  *                           * Indents SOURCE body in output
  114.  *                           * ASCII respects the TOC flag; removed extraneous
  115.  *                             newline after formfeed (so it's more like AutoDoc)
  116.  *                           * HTML output fixed to handle '<', '>', and '&'
  117.  *                           * LaTeX attributes and '%' handling added;
  118.  *                             fancied up the output a bit
  119.  *                           * RTF support added
  120.  *                           * Changed some fprintf()'s to fputc()'s for
  121.  *                             potentially lower overhead
  122.  *                           * Fixed line eater bug
  123.  *                           * More general fix to the TOC problem of including
  124.  *                             internal links when it wasn't selected
  125.  *  Modifications by FNC Slothouber.
  126.  *    01-April-1996  - v3.0h * Added ';' to > and < so lynx also recog. them
  127.  *                           * Fancied up the HTML output.
  128.  *    10-July-1996   - v3.0i * Bug Fix.  Both the options INTERNAL
  129.  *                             and INTERNALONLY did not work correctly.
  130.  *
  131.  *  Modifications by agi
  132.  *    15-Dec-1997    - v3.0j * cleaned the HTML-output, so it now conforms
  133.  *                             to the DTD for HTML-3.2
  134.  *                           * TOC now is an ordered list (<OL> and <LI>)
  135.  *                           * added "<!DOCTYPE..>"
  136.  *                           * added quotes to values of some HTML-attributes
  137.  *                           * more compatible implementation of the
  138.  *                             SGML-comment containing copyright-info
  139.  *                           * replaced all occurrences of <B><PRE>.. by
  140.  *                             <PRE><B>
  141.  *                           * replaced <H2/3> by <H1/2>
  142.  *                           * fixed two minor warnings reported by gcc -Wall
  143.  *
  144.  * NOTES
  145.  *   Has been succesfully compiled:
  146.  *     On an Amiga with SAS/C, DICE C and gcc (Amiga 1200)
  147.  *     On a Sun Sparc Station with gcc   (under SunOS 4.1)
  148.  *     On a Dec Alpha Station
  149.  *     Under HP/UX on a HP9000/800
  150.  *     On a Linux box with gcc.
  151.  * BUGS
  152.  *   - HTML output is not Lynx friendly -- attributes are applied
  153.  *     to leading white space =P ... solution: fix Lynx  >=)
  154.  *   - Can't get the escape character for @ to work in
  155.  *     AmigaGuide format.
  156.  *   Other bugs?
  157.  *     Catch them in a jar and send them to slothoub@xs4all.nl.
  158.  ****/
  159.  
  160. #include <stdio.h>
  161. #include <ctype.h>
  162. #include <stdlib.h>
  163. #include <string.h>
  164. #include <stdarg.h> /* for RB_Say() */
  165.  
  166. #include "robodoc.h"
  167.  
  168. #define RB_VERSION "3.0j"
  169.  
  170. static char RB_VER[] = "$VER: robodoc "RB_VERSION" (" __DATE__ ")";
  171.  
  172. #define COMMENT_ROBODOC \
  173.     "Generated with RoboDoc v" RB_VERSION " (" __DATE__ ")\n"
  174. #define COMMENT_COPYRIGHT \
  175.     "RoboDoc is copyright 1994-1997 by Maverick Software Development\n"
  176.  
  177. /****** RoboDoc.c/header_markers [3.0h]
  178.  * NAME
  179.  *   header_markers
  180.  * FUNCTION
  181.  *   These specify what robodoc will recognize as the beginning
  182.  *   of a header.
  183.  * SOURCE
  184.  */
  185.  
  186. char *header_markers[] = {
  187.     "/****",                    /* C, C++ */
  188.     "//****",                   /* C++ */
  189.     "(****",                    /* Pascal, Modula-2, B52 */
  190.     "{****",                    /* Pascal */
  191.     ";****",                    /* M68K assembler */
  192.     "****",                     /* M68K assembler */
  193.     "C     ****",               /* Fortran */
  194.     "REM ****",                 /* BASIC */
  195.     "%****",                    /* LaTeX, TeX, Postscript */
  196.     "      ****",               /* COBOL */
  197.     NULL } ;
  198.  
  199. /****/
  200.  
  201.  
  202. /****** RoboDoc.c/remark_markers [3.0h]
  203.  * NAME
  204.  *   remark_markers
  205.  * FUNCTION
  206.  *   These specify what robodoc will recognize as a comment marker.
  207.  * SOURCE
  208.  */
  209.  
  210. char *remark_markers[] = {
  211.     " *",                       /* C, C++, Pascal, Modula-2 */
  212.     "//",                       /* C++ */
  213.     "*",                        /* C, C++, M68K assembler, Pascal, Modula-2 */
  214.     ";*",                       /* M68K assembler */
  215.     ";",                        /* M68K assembler */
  216.     "C    ",                    /* Fortran */
  217.     "REM ",                     /* BASIC */
  218.     "%",                        /* LaTeX, TeX, Postscript */
  219.     "      *",                  /* COBOL */
  220.     NULL } ;
  221.  
  222. /****/
  223.  
  224.  
  225. /****** RoboDoc.c/end_markers [3.0h]
  226.  * NAME
  227.  *   end_markers
  228.  * FUNCTION
  229.  *   These specify what robodoc will recognize as the
  230.  *   end of a documentation header.
  231.  * SOURCE
  232.  */
  233.  
  234. char *end_markers[] = {
  235.     "/***",                     /* C, C++ */
  236.     "//***",                    /* C++ */
  237.     " ***",                     /* C, C++, Pascal, Modula-2 */
  238.     "{***",                     /* Pascal */
  239.     "(***",                     /* Pascal, Modula-2, B52 */
  240.     ";***",                     /* M68K assembler */
  241.     "***",                      /* M68K assembler */
  242.     "C     ***",                /* Fortran */
  243.     "REM ***",                  /* BASIC */
  244.     "%***",                     /* LaTeX, TeX, Postscript */
  245.     "      ***",                /* COBOL */
  246.     NULL } ;
  247.  
  248. /****/
  249.  
  250.  
  251. /* Header Types etc... */
  252.  
  253. enum { NO_HEADER = 0, MAIN_HEADER, GENERIC_HEADER, INTERNAL_HEADER, BLANK_HEADER } ;
  254.  
  255. /****** RoboDoc.c/output_mode [2.0]
  256.  * NAME
  257.  *   output_mode -- the mode of output
  258.  * FUNCTION
  259.  *   Controls which type of output will be generated.
  260.  * SOURCE
  261.  */
  262.  
  263. /* Output Modes */
  264.  
  265. enum { ASCII = 0, AMIGAGUIDE, HTML, LATEX, RTF, SIZE_MODES } ;
  266.  
  267. /* Reserved for Future Use */
  268.  
  269. enum { ANSI, GNUINFO, TROFF } ;
  270.  
  271.  
  272. /* Global Variable that defines the output mode */
  273.  
  274. int output_mode = ASCII;
  275.  
  276. /****/
  277.  
  278.  
  279. /****** RoboDoc.c/item_names [3.0g]
  280.  * NAME
  281.  *   item_names
  282.  * SYNOPSIS
  283.  *   char *item_names[]
  284.  * FUNCTION
  285.  *   used for strcmp() in RB_Get_Item_Type()
  286.  * AUTHOR
  287.  *   Koessi
  288.  * SEE ALSO
  289.  *   RB_Get_Item_Type(), item_attributes, item_attr_names
  290.  * SOURCE
  291.  */
  292.  
  293. char *item_names[] =
  294. {
  295.   NULL, "NAME", "COPYRIGHT", "SYNOPSIS",
  296.   "FUNCTION", "DESCRIPTION", "AUTHOR",
  297.   "CREATION DATE", "MODIFICATION HISTORY", "HISTORY",
  298.   "INPUTS", "ARGUMENTS", "OPTIONS", "PARAMETERS", "SWITCHES",
  299.   "OUTPUT", "SIDE EFFECTS", "RESULT", "RETURN VALUE",
  300.   "EXAMPLE", "NOTES", "DIAGNOSTICS",
  301.   "WARNINGS", "ERRORS", "BUGS", "TODO", "IDEAS",
  302.   "PORTABILITY", "SEE ALSO", "SOURCE",
  303.   "BEAST METHODS", "NEW METHODS",
  304.   "BEAST ATTRIBUTES", "NEW ATTRIBUTES",
  305.   NULL,
  306. };
  307.  
  308. /* Item Types */
  309. enum
  310. {
  311.   NO_ITEM = 0,  NAME_ITEM,  COPYRIGHT_ITEM,  SYNOPSIS_ITEM,
  312.   FUNCTION_ITEM,  DESCRIPTION_ITEM, AUTHOR_ITEM,
  313.   CREATION_DATE_ITEM,  MODIFICATION_HISTORY_ITEM,  HISTORY_ITEM,
  314.   INPUT_ITEM,  ARGUMENT_ITEM,  OPTION_ITEM,  PARAMETER_ITEM,  SWITCH_ITEM,
  315.   OUTPUT_ITEM,  SIDE_EFFECTS_ITEM,  RESULT_ITEM,  RETURN_VALUE_ITEM,
  316.   EXAMPLE_ITEM,  NOTE_ITEM,  DIAGNOSTICS_ITEM,
  317.   WARNING_ITEM,  ERROR_ITEM,  BUGS_ITEM,  TODO_ITEM,  IDEAS_ITEM,
  318.   PORTABILITY_ITEM,  SEE_ALSO_ITEM,  SOURCE_ITEM,
  319.   BEAST_METHODS,  NEW_METHODS,
  320.   BEAST_ATTRIBUTES,  NEW_ATTRIBUTES,  OTHER_ITEM,
  321.   NUMBER_OF_ITEMS
  322. };
  323.  
  324. /****/
  325.  
  326.  
  327. /****** RoboDoc.c/item_attributes [3.0h]
  328.  * NAME
  329.  *   item_attributes -- attributes of the various items
  330.  * FUNCTION
  331.  *   links each item type with a text attribute.
  332.  * SEE ALSO
  333.  *   RB_Get_Item_Type(), item_names, item_attr_names
  334.  * SOURCE
  335.  */
  336.  
  337. enum
  338. {
  339.   MAKE_NORMAL = -1,  MAKE_LARGE, MAKE_ITALICS, MAKE_NON_PROP, MAKE_SMALL,
  340.   MAKE_BOLD, MAKE_UNDERLINE, MAKE_SHINE, MAKE_HIGH, SIZE_ATTRIBUTES
  341. };
  342.  
  343. #define ITEM_NAME_LARGE_FONT (1<<0)
  344. #define TEXT_BODY_LARGE_FONT (1<<(MAKE_LARGE     + 1))
  345. #define TEXT_BODY_ITALICS    (1<<(MAKE_ITALICS   + 1))
  346. #define TEXT_BODY_NON_PROP   (1<<(MAKE_NON_PROP  + 1))
  347. #define TEXT_BODY_SMALL_FONT (1<<(MAKE_SMALL     + 1))
  348. #define TEXT_BODY_BOLD       (1<<(MAKE_BOLD      + 1))
  349. #define TEXT_BODY_UNDERLINE  (1<<(MAKE_UNDERLINE + 1))
  350. #define TEXT_BODY_SHINE      (1<<(MAKE_SHINE     + 1))
  351. #define TEXT_BODY_HIGHLIGHT  (1<<(MAKE_HIGH      + 1))
  352.  
  353. long item_attributes[NUMBER_OF_ITEMS] =
  354. {
  355.   0                                    , /* NO_ITEM */
  356.   ITEM_NAME_LARGE_FONT|TEXT_BODY_SHINE , /* NAME_ITEM */
  357.   ITEM_NAME_LARGE_FONT                 , /* COPYRIGHT_ITEM */
  358.   ITEM_NAME_LARGE_FONT                 , /* SYNOPSIS_ITEM */
  359.   ITEM_NAME_LARGE_FONT                 , /* FUNCTION_ITEM */
  360.   ITEM_NAME_LARGE_FONT                 , /* DESCRIPTION_ITEM */
  361.   ITEM_NAME_LARGE_FONT|TEXT_BODY_BOLD  , /* AUTHOR_ITEM */
  362.   ITEM_NAME_LARGE_FONT|TEXT_BODY_BOLD  , /* CREATION_DATE_ITEM */
  363.   ITEM_NAME_LARGE_FONT                 , /* MODIFICATION_HISTORY_ITEM */
  364.   ITEM_NAME_LARGE_FONT                 , /* HISTORY_ITEM */
  365.   ITEM_NAME_LARGE_FONT                 , /* INPUT_ITEM */
  366.   ITEM_NAME_LARGE_FONT                 , /* ARGUMENT_ITEM */
  367.   ITEM_NAME_LARGE_FONT                 , /* OPTION_ITEM */
  368.   ITEM_NAME_LARGE_FONT                 , /* PARAMETER_ITEM */
  369.   ITEM_NAME_LARGE_FONT                 , /* SWITCH_ITEM */
  370.   ITEM_NAME_LARGE_FONT                 , /* OUTPUT_ITEM */
  371.   ITEM_NAME_LARGE_FONT                 , /* SIDE_EFFECTS_ITEM */
  372.   ITEM_NAME_LARGE_FONT                 , /* RESULT_ITEM */
  373.   ITEM_NAME_LARGE_FONT                 , /* RETURN_VALUE_ITEM */
  374.   ITEM_NAME_LARGE_FONT                 , /* EXAMPLE_ITEM */
  375.   ITEM_NAME_LARGE_FONT|TEXT_BODY_SHINE , /* NOTE_ITEM */
  376.   ITEM_NAME_LARGE_FONT                 , /* DIAGNOSTICS_ITEM */
  377.   ITEM_NAME_LARGE_FONT                 , /* WARNING_ITEM */
  378.   ITEM_NAME_LARGE_FONT                 , /* ERROR_ITEM */
  379.   ITEM_NAME_LARGE_FONT|TEXT_BODY_SHINE , /* BUGS_ITEM */
  380.   ITEM_NAME_LARGE_FONT                 , /* TODO_ITEM */
  381.   ITEM_NAME_LARGE_FONT                 , /* IDEAS_ITEM */
  382.   ITEM_NAME_LARGE_FONT                 , /* PORTABILITY_ITEM */
  383.   ITEM_NAME_LARGE_FONT                 , /* SEE_ALSO_ITEM */
  384.   ITEM_NAME_LARGE_FONT                 , /* SOURCE_ITEM */
  385.   ITEM_NAME_LARGE_FONT                 , /* BEAST METHODS */
  386.   ITEM_NAME_LARGE_FONT                 , /* NEW METHODS */
  387.   ITEM_NAME_LARGE_FONT                 , /* BEAST ATTRIBUTES */
  388.   ITEM_NAME_LARGE_FONT                 , /* NEW ATTRIBUTES" */
  389.   0                                      /* OTHER_ITEM */
  390. };
  391.  
  392. /****/
  393.  
  394.  
  395. /****** RoboDoc.c/item_attr_names [3.0j]
  396.  * NAME
  397.  *   item_attr_names
  398.  * SYNOPSIS
  399.  *   char *item_attr_names[]
  400.  * FUNCTION
  401.  *   used for strcmp() in RB_Get_Item_Attr()
  402.  * AUTHOR
  403.  *   Koessi
  404.  * SEE ALSO
  405.  *   RB_Get_Item_Attr(), item_attributes, item_names
  406.  * SOURCE
  407.  */
  408.  
  409. char *item_attr_names[] =
  410. {
  411. /*  "NORMAL", */
  412.   "LARGE",  "ITALICS",  "NONPROP",  "SMALL",  "BOLD",
  413.   "UNDERLINE",   "SHINE",  "HIGHLIGHT"
  414. };
  415.  
  416. /* ASCII AMIGAGUIDE HTML LATEX RTF */
  417.  
  418. char *att_start_command[SIZE_ATTRIBUTES][SIZE_MODES] =
  419. {
  420.   {"", "@{b}"           , "<FONT SIZE=\"+1\">", "{\\large "   , "\\par\\fs28 "}, /* Large Font */
  421.   {"", "@{i}"           , "<I>"               , "{\\it "      , "\\i1 "       }, /* Italics. */
  422.   {"", ""               , ""                  , ""            , ""            }, /* NON-Proportional font. */
  423.   {"", ""               , "<SMALL>"           , "{\\small "   , "\\fs16 "     }, /* Small Font. */
  424.   {"", "@{b}"           , "<B>"               , "{\\bf "      , "\\b1 "       }, /* Bold. */
  425.   {"", "@{u}"           , "<U>"               , "\\underline{", "\\ul1 "      }, /* Underline */
  426.   {"", "@{fg shine}"    , "<EM>"              , "{\\em "      , ""            }, /* Shine */
  427.   {"", "@{fg highlight}", "<EM>"              , "{\\em "      , ""            }  /* Highlight */
  428. };
  429.  
  430. char *att_stop_command[SIZE_ATTRIBUTES][SIZE_MODES] =
  431. {
  432.   {"", "@{ub}"          , "</FONT>"           , "}"           , "\\fs20\\line "}, /* Large Font */
  433.   {"", "@{ui}"          , "</I>"              , "}"           , "\\i0 "        }, /* Italics. */
  434.   {"", ""               , ""                  , ""            , ""             }, /* NON-Proportional font. */
  435.   {"", ""               , "</SMALL>"          , "}"           , "\\fs20 "      }, /* Small Font. */
  436.   {"", "@{ub}"          , "</B>"              , "}"           , "\\b0 "        }, /* Bold. */
  437.   {"", "@{uu}"          , "</U>"              , "}"           , "\\ul0 "       }, /* Underline */
  438.   {"", "@{fg text}"     , "</EM>"             , "}"           , ""             }, /* Shine */
  439.   {"", "@{fg text}"     , "</EM>"             , "}"           , ""             }  /* Highlight */
  440. };
  441.  
  442. /****/
  443.  
  444.  
  445. /****** RoboDoc.c/course_of_action [2.0]
  446.  * NAME
  447.  *   course_of_action
  448.  * FUNCTION
  449.  *   Global Variable that defines the course of action.
  450.  * SOURCE
  451.  */
  452.  
  453. #define DO_SORT             (1<<0)
  454. #define DO_MAKE_XREFS       (1<<1)
  455. #define DO_USE_XREFS        (1<<2)
  456. #define DO_TOC              (1<<3)
  457. #define DO_MAKE_DOCUMENT    (1<<4)
  458. #define DO_INCLUDE_INTERNAL (1<<5)
  459. #define DO_INTERNAL_ONLY    (1<<6)
  460. #define DO_TELL             (1<<7)
  461.  
  462. int course_of_action = DO_MAKE_DOCUMENT;
  463.  
  464. /****/
  465.  
  466.  
  467. /****** RoboDoc.c/line_buffer [2.0]
  468.  * NAME
  469.  *   line_buffer -- global line buffer
  470.  * FUNCTION
  471.  *   Temporary storage area for lines
  472.  *   that are read from an input file.
  473.  * SOURCE
  474.  */
  475.  
  476. #define MAX_LINE_LEN 512
  477. char line_buffer[MAX_LINE_LEN];
  478.  
  479. /****/
  480.  
  481.  
  482. /****** RoboDoc.c/line_number [2.0]
  483.  * NAME
  484.  *   line_number -- global line counter
  485.  * FUNCTION
  486.  *   count the lines that are read from an input file.
  487.  * AUTHOR
  488.  *   Koessi
  489.  * SOURCE
  490.  */
  491.  
  492. int line_number = 0;
  493.  
  494. /****/
  495.  
  496.  
  497. /****** RoboDoc.c/use [3.0h]
  498.  * NAME
  499.  *   use -- usage string
  500.  * FUNCTION
  501.  *   inform the user how to use me
  502.  * AUTHOR
  503.  *   Koessi
  504.  * SOURCE
  505.  */
  506.  
  507. char use[] =
  508.   "\nRoboDoc v" RB_VERSION ", autodocs formatter\n\n"
  509.   "(c) " __DATE__ ", Maverick Software Development\n"
  510.   "Original idea and program:  Jacco van Weert   <weertj@iaehv.nl>\n"
  511.   "Version 2.0 and up:         Frans Slothouber  <slothoub@xs4all.nl>\n"
  512.   "RTF support:                Anthon Pang       <apang@mindlink.net>\n"
  513.   "\nFORMAT\n"
  514.   "  robodoc filename docfilename\n"
  515.   "\nIn addition you can use one or more of the following options:\n"
  516.   "  GENXREF <xref_filename>  - to generate an xref file.\n"
  517.   "  XREF <xreflist_filename> - if you want to use xref files to create\n"
  518.   "                             cross links\n"
  519.   "  TABSIZE <nr_sp>          - convert each TAB to nr_sp of spaces.\n"
  520.   "  TOC          - a table of contents will be generated.\n"
  521.   "  SORT         - the headers will be sorted.\n"
  522.   "  -v           - tell robodoc to tell you all about it.\n"
  523.   "  INTERNAL     - headers marked internal will also be included.\n"
  524.   "  INTERNALONLY - only headers marked internal will be included.\n"
  525.   "\nThe type of output is selected with one of the following switches:\n"
  526.   "  ASCII, GUIDE, HTML, LATEX, or RTF\n"
  527.   "\nThe following abbreviations are also allowed:\n"
  528.   "  TOC = -t  XREF = -x   SORT = -s  INTERNAL = -i \n"
  529.   "  GENXREF = -g  INTERNALONLY = -io  TABSIZE = -ts\n";
  530.  
  531. /****/
  532.  
  533.  
  534. /* Global variables & prototypes */
  535.  
  536. char *whoami = NULL; /* me,myself&i */
  537. int tab_size = 8;
  538.  
  539. struct RB_header *first_header = NULL;
  540. struct RB_header *last_header  = NULL;
  541. struct RB_link   *first_link   = NULL;
  542.  
  543. int header_index_size = 0 ;
  544. struct RB_header **header_index = NULL ;
  545.  
  546. int link_index_size = 0 ;
  547. struct RB_link   **link_index   = NULL ;
  548.  
  549. FILE *document = NULL;
  550. FILE *dest_doc = NULL;
  551. FILE *xreffiles_file = NULL;
  552. FILE *xref_file = NULL;
  553.  
  554. void RB_Analyse_Document  (FILE *);
  555. void RB_Analyse_Xrefs     (FILE *);
  556. void RB_Analyse_Arguments (int, char **, char **, char **);
  557. void RB_Analyse_Defaults_File(void);
  558.  
  559. int RB_Find_Marker     (FILE *);
  560. int RB_Find_End_Marker (FILE *, int *);
  561. int RB_Find_Item       (char **, char **);
  562. char *RB_Find_Header_Name(void);
  563.  
  564. void RB_Generate_xrefs         (FILE * dest_doc, char *, char *) ;
  565. void RB_Generate_Documentation (FILE *, char *, char *) ;
  566. void RB_Generate_Item_Doc      (FILE *, char *, char *, char *, char *, int) ;
  567. void RB_Generate_Item_Body     (FILE *, char *, char *, char *, char *, int) ;
  568. void RB_Generate_Header_Name   (FILE *, char *) ;
  569. void RB_Generate_Item_Name     (FILE *, int) ;
  570. void RB_Generate_Doc_Start     (FILE *, char *, char *) ;
  571. void RB_Generate_Doc_End       (FILE *, char *) ;
  572. void RB_Generate_Header_Start  (FILE *, struct RB_header *) ;
  573. void RB_Generate_Header_End    (FILE *, struct RB_header *) ;
  574. void RB_Close_The_Shop         (void);
  575. void RB_Make_Index_Tables      (void) ;
  576.  
  577. void RB_Remove_From_List (struct RB_header **, struct RB_header *);
  578. void RB_Insert_In_List   (struct RB_header **, struct RB_header *);
  579. void RB_Slow_Sort        (void);
  580. void RB_Add_Link         (void);
  581. int  RB_Find_Link        (char *, char **, char **);
  582.  
  583. char *RB_FilePart      (char *);
  584. int   RB_Get_Item_Type (char *);
  585. int   RB_WordLen       (char *);
  586. char *RB_StrDup        (char *);
  587. char *RB_CookStr       (char *);
  588.  
  589. struct RB_header *RB_Alloc_Header(void);
  590. void   RB_Free_Header(struct RB_header *);
  591.  
  592. struct RB_link *RB_Alloc_Link(char *, char *);
  593. void   RB_Free_Link(struct RB_link *);
  594.  
  595. void   RB_Say   (char *, ...);
  596. void   RB_Panic (char *, ...);
  597.  
  598. char *RB_Skip_Remark_Marker (char *line_buffer) ;
  599.  
  600. /********/
  601.  
  602.  
  603. /****i* RoboDoc.c/_main [2.0d]
  604.  * NAME
  605.  *   _main -- Entry point of RoboDoc.c
  606.  * SYNOPSIS
  607.  *   main (int argc, char **argv)
  608.  * FUNCTION
  609.  *   Get and parse the arguments.
  610.  *   Analyse document.
  611.  * SOURCE
  612.  */
  613.  
  614. int main(int argc, char **argv)
  615. {
  616.   char *file_with_xrefs, *output_file_for_xrefs ;
  617.  
  618.   whoami = argv[0] ;  /* global me,myself&i */
  619.   if ((argc < 3) || (*argv[1] == '?'))
  620.   {
  621.     printf(use);
  622.   }
  623.   else
  624.   {
  625.     RB_Analyse_Arguments(argc, argv, &file_with_xrefs, &output_file_for_xrefs);
  626.  
  627.     RB_Say("Analysing Defaults File\n") ;
  628.     RB_Analyse_Defaults_File () ;
  629.  
  630.     RB_Say("trying to open source file \"%s\"\n", argv[1]);
  631.     if ((document = fopen(argv[1], "r")) != NULL)
  632.     {
  633.       RB_Say("analysing source file \"%s\"\n", argv[1]);
  634.       RB_Analyse_Document(document);
  635.  
  636.       if (course_of_action & DO_SORT)
  637.       {
  638.         RB_Say("sorting headers\n");
  639.         RB_Slow_Sort();
  640.       }
  641.       if ((course_of_action & DO_USE_XREFS) && file_with_xrefs)
  642.       {
  643.         if ((xreffiles_file = fopen(file_with_xrefs, "r")) != NULL)
  644.         {
  645.           RB_Analyse_Xrefs(xreffiles_file);
  646.         }
  647.         else
  648.         {
  649.           RB_Panic("can't open file with xref files \"%s\"\n", file_with_xrefs);
  650.         }
  651.       }
  652.       if (course_of_action & DO_MAKE_DOCUMENT)
  653.       {
  654.         RB_Say("trying to open destination file \"%s\"\n", argv[2]);
  655.         if ((dest_doc = fopen(argv[2], "w")) != NULL)
  656.         {
  657.           RB_Say("generating documentation\n");
  658.           RB_Generate_Documentation(dest_doc, RB_FilePart(argv[1]), RB_FilePart(argv[2]));  /* additional function *koessi */
  659.           fclose(dest_doc);
  660.           dest_doc = NULL;
  661.         }
  662.         else RB_Panic("can't open destination file \"%s\"\n", argv[2]);
  663.       }
  664.       if ((course_of_action & DO_MAKE_XREFS) && output_file_for_xrefs)
  665.       {
  666.         RB_Say("trying to open xref destination file \"%s\"\n", output_file_for_xrefs);
  667.         if ((dest_doc = fopen(output_file_for_xrefs, "w")) != NULL)
  668.         {
  669.           RB_Say("generating xref destination file \"%s\"\n", output_file_for_xrefs);
  670.           RB_Generate_xrefs(dest_doc, argv[1], argv[2]);
  671.           fclose(dest_doc);
  672.           dest_doc = NULL;
  673.         }
  674.         else RB_Panic("can't open xref destination file \"%s\"\n", output_file_for_xrefs);
  675.       }
  676.     }
  677.     else RB_Panic("can't open source file \"%s\"\n", argv[1]);
  678.   }
  679.   RB_Say("Ready\n");
  680.   RB_Close_The_Shop();
  681.   return (0);
  682. }
  683.  
  684. /*** main ***/
  685.  
  686.  
  687. /****** RoboDoc.c/RB_FilePart [2.0x]
  688.  * NAME
  689.  *   RB_FilePart
  690.  * SYNOPSIS
  691.  *   char *RB_FilePart(char *file_name)
  692.  * FUNCTION
  693.  *   return the basename (like Amiga/Dos/FilePart())
  694.  * NOTES
  695.  *   koessi
  696.  * SEE ALSO
  697.  * SOURCE
  698.  */
  699.  
  700. char *RB_FilePart(char *file_name)
  701. {
  702.   char *cur_char;
  703.   char c;
  704.  
  705.   if ((cur_char = file_name) != NULL)
  706.   {
  707.     for (; (c = *cur_char) != '\0'; ++cur_char)
  708.     {
  709.       if ((c == '/') || (c == ':'))
  710.       {
  711.         ++cur_char;
  712.         while ('/' == *cur_char)
  713.           ++cur_char;
  714.  
  715.         if (*cur_char)
  716.           file_name = cur_char;
  717.       }
  718.     }
  719.   }
  720.   return (file_name);
  721. }
  722.  
  723. /*** RB_File_Part ***/
  724.  
  725.  
  726. /****** RoboDoc.c/RB_Get_Item_Type [3.0b]
  727.  * NAME
  728.  *   RB_Get_Item_Type -- shortcut
  729.  * SYNOPSIS
  730.  *   int RB_Get_Item_Type( char *cmp_name )
  731.  * FUNCTION
  732.  *   return the item_type represented by the given string
  733.  * INPUTS
  734.  *   char *cmp_name          -- item_name to evaluate
  735.  * RESULT
  736.  *   int                     -- the right item_type or NO_ITEM
  737.  * NOTES
  738.  *   uses global char *item_names[]
  739.  * AUTHOR
  740.  *   Koessi
  741.  * SEE ALSO
  742.  *   RB_Analyse_Defaults_File(), RB_Get_Item_Attr()
  743.  * SOURCE
  744.  */
  745.  
  746. int RB_Get_Item_Type(char *cmp_name)
  747. {
  748.   int  item_type;
  749.   for (item_type = NAME_ITEM; item_type < OTHER_ITEM; ++item_type)
  750.   {
  751.     if (!strncmp(item_names[item_type], cmp_name, strlen(item_names[item_type])))
  752.       return(item_type);
  753.   }
  754.   return(NO_ITEM);
  755. }
  756.  
  757. /*** RB_Get_Item_Type ***/
  758.  
  759.  
  760. /****** RoboDoc.c/RB_Get_Item_Attr [3.0b]
  761.  *
  762.  * NAME
  763.  *   RB_Get_Item_Attr -- shortcut
  764.  * SYNOPSIS
  765.  *   int RB_Get_Item_Attr( char *cmp_name )
  766.  * FUNCTION
  767.  *   return the item_attr represented by the given string
  768.  * INPUTS
  769.  *   char *cmp_name  -- item_attr_name to evaluate
  770.  * RESULT
  771.  *   int             -- the right item_attr or NULL
  772.  * NOTES
  773.  *   uses global char *item_attr_names[]
  774.  * AUTHOR
  775.  *   Koessi
  776.  * SEE ALSO
  777.  *   RB_Analyse_Defaults_File(), RB_Get_Item_Type()
  778.  * SOURCE
  779.  */
  780.  
  781. int RB_Get_Item_Attr(char *cmp_name)
  782. {
  783.   int  item_attr;
  784.   for (item_attr = MAKE_LARGE; item_attr < SIZE_ATTRIBUTES; ++item_attr)
  785.     if (!strcmp(item_attr_names[item_attr], cmp_name))
  786.       return(item_attr);
  787.   if (strcmp("NORMAL", cmp_name))
  788.   {
  789.     printf ("%s: Warning unknown attribute [%s] in defaults file.\n",whoami, cmp_name) ;
  790.   }
  791.   return(MAKE_NORMAL);
  792. }
  793.  
  794. /*** RB_Get_Item_Attr ***/
  795.  
  796.  
  797. /****** RoboDoc.c/RB_Analyse_Defaults_File [3.0b]
  798.  * NAME
  799.  *   RB_Analyse_Defaults_file -- read default from defaults file
  800.  * SYNOPSIS
  801.  *   RB_Analyse_Defaults_file
  802.  * FUNCTION
  803.  *   Read the default vaules from the default file.
  804.  * SEE ALSO
  805.  * SOURCE
  806.  */
  807.  
  808. void RB_Analyse_Defaults_File()
  809. {
  810.   FILE *defaults_file;
  811.  
  812.   if ((defaults_file = fopen("robodoc.defaults", "r")) != NULL)
  813.   {
  814.     while (!feof(defaults_file))
  815.     {
  816.       char *cur_char;
  817.       *line_buffer = '\0';
  818.  
  819.       fgets(line_buffer, MAX_LINE_LEN, defaults_file);
  820.  
  821.       if (*line_buffer != '\n')
  822.       {
  823.         int   item_type;
  824.         item_type = RB_Get_Item_Type(line_buffer);
  825.         if (item_type != NO_ITEM)
  826.         {
  827.           char *values ;
  828.  
  829.           item_attributes[item_type] = ITEM_NAME_LARGE_FONT ;
  830.  
  831.           cur_char = line_buffer + strlen(item_names[item_type]) ;
  832.           for (; *cur_char && isspace(*cur_char); cur_char++) ;
  833.  
  834.           while (*cur_char)
  835.           {
  836.             for (values = cur_char;
  837.                  *cur_char && !isspace(*cur_char);
  838.                  cur_char++) ;
  839.             if (*cur_char)
  840.             {
  841.               int item_attr;
  842.               *cur_char = '\0';
  843.               item_attr = RB_Get_Item_Attr(values) ;
  844.               if (item_attr != MAKE_NORMAL)
  845.               {
  846.                 RB_Say ("Default: %s = %s\n", item_names[item_type],
  847.                                               item_attr_names[item_attr]) ;
  848.                 item_attributes[item_type] |= (1<<(item_attr+1)) ;
  849.               }
  850.             }
  851.             for (cur_char++; *cur_char && isspace(*cur_char); cur_char++) ;
  852.           }
  853.         }
  854.       }
  855.     }
  856.     fclose(defaults_file);
  857.   }
  858.   else
  859.   {
  860.     printf("%s: WARNING, robodoc.defaults file was not found.\n", whoami);
  861.     printf("\t\tyou should really use one.\n");
  862.   }
  863. }
  864.  
  865. /*** RB_Analyse_Defaults_File ***/
  866.  
  867.  
  868. /****** RoboDoc.c/RB_Analyse_Arguments [3.0h]
  869.  * NAME
  870.  *   RB_Analyse_Arguments
  871.  * SYNOPSIS
  872.  *   RB_Analyse_Arguments (argc, argv, file_with_xrefs,
  873.  *                         output_file_for_xrefs)
  874.  *   RB_Analyse_Arguments (int, char **, char **, char **)
  875.  * FUNCTION
  876.  *   Get and parse the arguments.
  877.  * SEE ALSO
  878.  * SOURCE
  879.  */
  880.  
  881. void RB_Analyse_Arguments(int argc, char **argv,
  882.                           char **file_with_xrefs,
  883.                           char **output_file_for_xrefs)
  884. {
  885.   char **parameter;
  886.   int parameter_nr;
  887.  
  888.   for (parameter_nr = argc - 3, parameter = argv + 3;
  889.        parameter_nr > 0;
  890.        parameter++, parameter_nr--)
  891.   {
  892.     char *cur_char ;
  893.  
  894.     for (cur_char = *parameter ; *cur_char ; cur_char++)
  895.         *cur_char = toupper(*cur_char) ;
  896.  
  897.     if      (!strcmp(*parameter, "HTML"))  output_mode = HTML;
  898.     else if (!strcmp(*parameter, "GUIDE")) output_mode = AMIGAGUIDE;
  899.     else if (!strcmp(*parameter, "LATEX")) output_mode = LATEX;
  900.     else if (!strcmp(*parameter, "ASCII")) output_mode = ASCII;
  901.     else if (!strcmp(*parameter, "RTF"))   output_mode = RTF;
  902.     else if (!strcmp(*parameter, "SORT") ||  !strcmp(*parameter, "-S"))
  903.       course_of_action |= DO_SORT;
  904.     else if (!strcmp(*parameter, "INTERNAL") || !strcmp(*parameter, "-I"))
  905.       course_of_action |= DO_INCLUDE_INTERNAL;
  906.     else if (!strcmp(*parameter, "INTERNALONLY") || !strcmp(*parameter, "-IO"))
  907.       course_of_action |= DO_INTERNAL_ONLY;
  908.     else if (!strcmp(*parameter, "TOC") || !strcmp(*parameter, "-T"))
  909.       course_of_action |= DO_TOC;
  910.     else if (!strcmp(*parameter, "-V")) course_of_action |= DO_TELL;
  911.     else if (!strcmp(*parameter, "XREF") || !strcmp(*parameter, "-X"))
  912.     {
  913.       if (--parameter_nr)
  914.       {
  915.         parameter++ ;
  916.         *file_with_xrefs = *parameter ;
  917.         RB_Say ("XREF=\"%s\"\n", *file_with_xrefs) ;
  918.         course_of_action |= DO_USE_XREFS ;
  919.       }
  920.       else RB_Panic("you must specify a xref file with the XREF option\n");
  921.     }
  922.     else if (!strcmp(*parameter, "TABSIZE") || !strcmp(*parameter, "-TS"))
  923.     {
  924.       if (--parameter_nr)
  925.       {
  926.         parameter++ ;
  927.         tab_size = atoi(*parameter);
  928.       }
  929.       else
  930.       {
  931.         RB_Panic("you must specify the number of spaces with the TABSIZE option\n");
  932.       }
  933.     }
  934.     else if (!strcmp(*parameter, "GENXREF") || !strcmp(*parameter, "-G"))
  935.     {
  936.       if (--parameter_nr)
  937.       {
  938.         ++parameter;
  939.         *output_file_for_xrefs = *parameter;
  940.         RB_Say("GENXREF=\"%s\"\n", *output_file_for_xrefs);
  941.         course_of_action |= DO_MAKE_XREFS;
  942.         course_of_action &= ~DO_MAKE_DOCUMENT;
  943.       }
  944.       else RB_Panic("you must specify a xref file with the GENXREF option\n");
  945.     }
  946.     else RB_Panic("unknown option \"%s\"\n", *parameter);
  947.   }
  948.  
  949.   if ((course_of_action & DO_USE_XREFS) && (output_mode == ASCII || output_mode == LATEX))
  950.   {
  951.     printf("%s: WARNING, you can not use xrefs when you generate\n"
  952.            "\t\tdocumentation in ASCII or LaTeX [discarding switch]\n", argv[0]);
  953.     course_of_action &= ~DO_USE_XREFS;
  954.   }
  955. }
  956.  
  957. /*** RB_Analyse_Arguments ***/
  958.  
  959.  
  960. /****** RoboDoc.c/RB_Analyse_Xrefs [3.0b]
  961.  * NAME
  962.  *   RB_Analyse_Xrefs -- scan the xref files.
  963.  * SYNOPSIS
  964.  *   RB_Analyse_Xrefs (xreffiles_file)
  965.  *   RB_Analyse_Xrefs (FILE *)
  966.  * FUNCTION
  967.  *   Scan the file xreffiles_file. This file contains the
  968.  *   names of one or more xref files. All the references in the
  969.  *   files are scaned and stored in a link list of the type
  970.  *   RB_link.
  971.  *   These xref files can be generated with robodoc.
  972.  * INPUTS
  973.  *   xreffiles_file - a file pointer to the file with xref file
  974.  *   names.
  975.  * RESULT
  976.  *   none
  977.  * BUGS
  978.  *   Might fail if there are syntax errors in one of the xref
  979.  *   files.
  980.  * SEE ALSO
  981.  *   RB_Generate_xrefs, RB_Add_Link
  982.  * SOURCE
  983.  */
  984.  
  985. void RB_Analyse_Xrefs(FILE * xreffiles_file)
  986. {
  987.   while(!feof(xreffiles_file))
  988.   {
  989.     fgets(line_buffer, MAX_LINE_LEN, xreffiles_file);
  990.     if (!feof(xreffiles_file))
  991.     {
  992.       char *cur_char;
  993.       cur_char = line_buffer; find_eol ;
  994.       if (*cur_char == '\n') *cur_char = '\0';
  995.       if ((xref_file = fopen(line_buffer, "r")) != NULL)
  996.       {
  997.         int xrefs_found  = FALSE;
  998.         int end_of_xrefs = FALSE;
  999.  
  1000.         while(!feof(xref_file) && !xrefs_found)
  1001.         {
  1002.           fgets(line_buffer, MAX_LINE_LEN, xref_file);
  1003.           if (!feof(xref_file) && !strncmp("XREF:", line_buffer, 5))
  1004.             xrefs_found = TRUE;
  1005.         }
  1006.  
  1007.         while(!feof(xref_file) && !end_of_xrefs)
  1008.         {
  1009.           fgets(line_buffer, MAX_LINE_LEN, xref_file);
  1010.           if (!feof(xref_file))
  1011.           {
  1012.             cur_char = line_buffer; find_quote ;
  1013.             if (*cur_char == '\"') RB_Add_Link();
  1014.             else end_of_xrefs = TRUE;
  1015.           }
  1016.         }
  1017.         fclose(xref_file);
  1018.         xref_file = NULL;
  1019.       }
  1020.       else RB_Panic("could not open xref file \"%s\"\n", line_buffer);
  1021.     }
  1022.   }
  1023. }
  1024.  
  1025. /*** RB_Analyse_Xrefs */
  1026.  
  1027.  
  1028. /****i* RoboDoc.c/RB_Add_Link [3.0b]
  1029.  * NAME
  1030.  *   RB_Add_Link -- add a reference link to the list
  1031.  * SYNOPSIS
  1032.  *   void RB_Add_Link ()
  1033.  * FUNCTION
  1034.  *   Adds a reference from a xref file to the linked list
  1035.  *   with references.
  1036.  * INPUTS
  1037.  *   Uses the global variable line_buffer and first_link.
  1038.  * NOTES
  1039.  *   Makes sneaky use of the function RB_Insert_In_List.
  1040.  * SEE ALSO
  1041.  *   RB_Analyse_Xrefs, RB_link.
  1042.  * SOURCE
  1043.  */
  1044.  
  1045. void RB_Add_Link()
  1046. {
  1047.   char *label_name, *file_name;
  1048.   struct RB_link *new_link;
  1049.   char *cur_char = line_buffer;
  1050.   find_quote ; label_name = ++cur_char; find_quote ; *cur_char++ = '\0';
  1051.   find_quote ; file_name  = ++cur_char; find_quote ; *cur_char = '\0';
  1052.   RB_Say("adding xref link \"%s\"->\"%s\"\n", label_name, file_name);
  1053.  
  1054.   new_link = RB_Alloc_Link(label_name, file_name);
  1055.   RB_Insert_In_List((struct RB_header **)&first_link,
  1056.                     (struct RB_header *)new_link);
  1057. }
  1058.  
  1059. /*** RB_Add_Link ***/
  1060.  
  1061.  
  1062. /****** RoboDoc.c/RB_Analyse_Document [3.0i]
  1063.  * NAME
  1064.  *   RB_Analyse_Document -- scan document for headers and store them
  1065.  * SYNOPSIS
  1066.  *   RB_Analyse_Document (document)
  1067.  *   RB_Analyse_Document (FILE *)
  1068.  * FUNCTION
  1069.  *   Searches the document for headers. Stores information about
  1070.  *   any headers that are found in a linked list. Information
  1071.  *   that is stored includes, the name of the header, its version
  1072.  *   number, and its contents.
  1073.  * INPUTS
  1074.  *   document - a pointer to a file with the document to be
  1075.  *              analysed
  1076.  *   the gobal buffer line_buffer.
  1077.  * RESULT
  1078.  *   1)   A linked list pointed to by the global variable
  1079.  *        first_header that contains information about each
  1080.  *        header.
  1081.  * NOTES
  1082.  *   Using fseek and ftell because gcc doesn't know fgetpos and fsetpos,
  1083.  *   on the sun unix system that I use
  1084.  * SEE ALSO
  1085.  *   RB_Find_Marker
  1086.  * SOURCE
  1087.  */
  1088.  
  1089. void RB_Analyse_Document (FILE * document)
  1090. {
  1091.   int header_type;
  1092.   int real_size;
  1093.   char *name ;
  1094.  
  1095.   for (;
  1096.        (header_type = RB_Find_Marker(document)) != NO_HEADER ;
  1097.       )
  1098.   {
  1099.     long cur_file_pos;
  1100.     struct RB_header *new_header;
  1101.     if (!
  1102.         (
  1103.          ((header_type == INTERNAL_HEADER) && !(course_of_action & (DO_INCLUDE_INTERNAL | DO_INTERNAL_ONLY)))
  1104.          ||
  1105.          ((header_type != INTERNAL_HEADER) && (course_of_action & DO_INTERNAL_ONLY))
  1106.          ||
  1107.          (header_type == BLANK_HEADER)
  1108.         )
  1109.        )
  1110.     {
  1111.       new_header = RB_Alloc_Header();
  1112.       RB_Insert_In_List(&first_header, new_header);
  1113.       new_header->type = header_type;
  1114.       if ((new_header->name = RB_Find_Header_Name()) != NULL)
  1115.       {
  1116.         RB_Say("found header [line %5d]: \"%s\"\n", line_number, new_header->name);
  1117.         new_header->function_name = RB_FilePart(new_header->name);
  1118.         cur_file_pos = (long)ftell(document);
  1119.         if ((real_size = RB_Find_End_Marker(document, &new_header->size)) != 0)
  1120.         {
  1121.           char *contents;
  1122.  
  1123.           fseek(document, cur_file_pos, 0);
  1124.           if ((contents = (char *)malloc((new_header->size + 2) * sizeof(char))) != NULL)
  1125.           {
  1126.             fread(contents, new_header->size, sizeof(char), document);
  1127.             contents[real_size]  = '\0';
  1128.             new_header->contents = contents;
  1129.             new_header->size     = real_size;
  1130.           } else RB_Panic("out of memory! [Alloc Header Contents]\n");
  1131.         }
  1132.         else
  1133.         {
  1134.           RB_Panic("found header with no end marker \"%s\"\n", new_header->name);
  1135.         }
  1136.       }
  1137.       else
  1138.       {
  1139.         RB_Panic("found header marker but no name [line %d]\n", line_number);
  1140.       }
  1141.     }
  1142.     else
  1143.     {
  1144.       if (header_type != BLANK_HEADER)
  1145.       {
  1146.         if ((name = RB_Find_Header_Name()) != NULL)
  1147.         {
  1148.           if ((real_size = RB_Find_End_Marker(document, &new_header->size)) == 0)
  1149.           {
  1150.             RB_Panic("found header with no end marker \"%s\"\n", name);
  1151.           }
  1152.         }
  1153.         else
  1154.         {
  1155.           RB_Panic("found header marker but no name [line %d]\n", line_number);
  1156.         }
  1157.       }
  1158.     }
  1159.   }
  1160. }
  1161.  
  1162. /*** RB_Analyse_Document ***/
  1163.  
  1164.  
  1165. /****** RoboDoc.c/RB_Find_Marker [3.0h]
  1166.  * NAME
  1167.  *   RB_Find_Marker -- Search for header marker in document.
  1168.  * SYNOPSIS
  1169.  *   header_type = RB_Find_Marker (document)
  1170.  *             int RB_Find_Marker (FILE *)
  1171.  * FUNCTION
  1172.  *   Read document file line by line, and search each line for the
  1173.  *   any of the headers defined in the array  header_markers
  1174.  * INPUTS
  1175.  *   document - pointer to the file to be searched.
  1176.  *   the gobal buffer line_buffer.
  1177.  * RESULT
  1178.  *   header type
  1179.  *   can be:
  1180.  *    (1) NO_HEADER - no header found, end of file reached
  1181.  *    (2) MAIN_HEADER
  1182.  *    (3) GENERIC_HEADER
  1183.  *    (4) INTERNAL_HEADER
  1184.  * SEE ALSO
  1185.  *   RB_Find_End_Marker
  1186.  * SOURCE
  1187.  */
  1188.  
  1189. int RB_Find_Marker(FILE * document)
  1190. {
  1191.   int found;
  1192.   int marker, marker_type ;
  1193.   char *cur_char, *cur_mchar ;
  1194.  
  1195.   found = FALSE ;
  1196.   while( !feof(document) && !found)
  1197.   {
  1198.     *line_buffer = '\0';
  1199.     fgets(line_buffer, MAX_LINE_LEN, document);
  1200.     if (!feof(document))
  1201.     {
  1202.       line_number++;
  1203.       for (marker=0 ;
  1204.            ((cur_mchar = header_markers[marker]) != NULL) && !found ;
  1205.            marker++)
  1206.       {
  1207.         for (found = TRUE, cur_char = line_buffer;
  1208.              *cur_mchar && *cur_char && found;
  1209.               cur_mchar++, cur_char++)
  1210.         {
  1211.           if (*cur_mchar != *cur_char) found = FALSE ;
  1212.         }
  1213.       }
  1214.       if (found)
  1215.       {
  1216.         switch (*cur_char)
  1217.         {
  1218.           case 'h': marker_type = MAIN_HEADER ;     break ;
  1219.           case '*': marker_type = GENERIC_HEADER ;  break ;
  1220.           case 'i': marker_type = INTERNAL_HEADER ; break ;
  1221.           default:
  1222.             RB_Say("%s: WARNING, [line %d] undefined headertype, using GENERIC\n",
  1223.                     whoami, line_number);
  1224.             marker_type = GENERIC_HEADER;
  1225.         }
  1226.       }
  1227.     }
  1228.   }
  1229.   if (!found || feof(document)) return (NO_HEADER) ;
  1230.  
  1231.   if (marker_type == GENERIC_HEADER)
  1232.   {
  1233.     skip_while (*cur_char == '*') ;
  1234.     if (*cur_char == '/')
  1235.       return BLANK_HEADER;
  1236.   }
  1237.  
  1238.   return marker_type;
  1239. }
  1240.  
  1241. /*** RB_Find_Marker ***/
  1242.  
  1243.  
  1244. /****** RoboDoc.c/RB_Find_End_Marker [3.0h]
  1245.  * NAME
  1246.  *   RB_Find_End_Marker -- Search for end marker in document.
  1247.  * SYNOPSIS
  1248.  *   result = RB_Find_End_Marker (document)
  1249.  *        int RB_Find_End_Marker (FILE *)
  1250.  * FUNCTION
  1251.  *   Searches line by line till any of the markers in the
  1252.  *   array: end_markers is found.
  1253.  * INPUTS
  1254.  *   document   - pointer to the file to be searched.
  1255.  *   int *total_size - external size
  1256.  *   the gobal buffer line_buffer.
  1257.  * RESULT
  1258.  *                real_size if end marker was found
  1259.  *   0          - no end marker was found
  1260.  * SEE ALSO
  1261.  *   RB_Find_Marker
  1262.  * SOURCE
  1263.  */
  1264.  
  1265. int RB_Find_End_Marker(FILE * document, int *total_size)
  1266. {
  1267.   int real_size = 0;
  1268.   int found = FALSE ;
  1269.   int marker ;
  1270.   int   line_len;
  1271.   char *cur_char, *cur_mchar ;
  1272.  
  1273.   while (!feof(document) && !found)
  1274.   {
  1275.     cur_char = line_buffer;
  1276.     *cur_char  = '\0';
  1277.     fgets(cur_char, MAX_LINE_LEN, document);
  1278.     ++line_number;                  /* global linecounter *koessi*/
  1279.  
  1280.     line_len   = strlen(cur_char);
  1281.     real_size += line_len;
  1282.  
  1283.     if (!feof(document))
  1284.     {
  1285.       for (marker=0 ;
  1286.            ((cur_mchar = end_markers[marker]) != NULL) && !found ;
  1287.            marker++)
  1288.       {
  1289.         for (found = TRUE, cur_char = line_buffer;
  1290.              *cur_mchar && *cur_char && found;
  1291.               cur_mchar++, cur_char++)
  1292.         {
  1293.           if (*cur_mchar != *cur_char) found = FALSE ;
  1294.         }
  1295.       }
  1296.     }
  1297.   }
  1298.   if (total_size)
  1299.       *total_size = real_size ;
  1300.   if (found) return (real_size - line_len) ;
  1301.   else return(0);
  1302. }
  1303.  
  1304. /*** RB_Find_End_Marker ***/
  1305.  
  1306.  
  1307. /****** RoboDoc.c/RB_Find_Header_Name   [3.0b]
  1308.  * NAME
  1309.  *   RB_Find_Header_Name -- search for header name
  1310.  * SYNOPSIS
  1311.  *   result = RB_Find_Header_Name ()
  1312.  *      char *RB_Find_Header_Name ()
  1313.  * FUNCTION
  1314.  *   Searches the line buffer for the header name.
  1315.  *   It assumes that the header name follows after the
  1316.  *   header marker, seperated by one or more spaces, and terminated
  1317.  *   by one or more spaces or a '\n'.
  1318.  *   It allocates an array of chars and copies the name to this array.
  1319.  * INPUTS
  1320.  *   the gobal buffer line_buffer.
  1321.  * RESULT
  1322.  *   pointer to the allocated array of chars that contains the name,
  1323.  *   terminated with a '\0'.
  1324.  *   NULL if no header name was found.
  1325.  * MODIFICATION HISTORY
  1326.  *   8. August 1995      --  optimized by koessi
  1327.  * SEE ALSO
  1328.  *   RB_Find_Function_Name(), RB_WordLen(), RB_StrDup()
  1329.  * SOURCE
  1330.  */
  1331.  
  1332. char *RB_Find_Header_Name(void)
  1333. {
  1334.   char *cur_char;
  1335.  
  1336.   cur_char = line_buffer;
  1337.   skip_while (*cur_char != '*') ;
  1338.   skip_while (!isspace(*cur_char)) ;
  1339.   skip_while (isspace(*cur_char)) ;
  1340.   if (*cur_char)
  1341.   {
  1342.     char *end_char, old_char ;
  1343.     end_char  = cur_char + RB_WordLen(cur_char);
  1344.     old_char  = *end_char;
  1345.     *end_char = '\0';
  1346.     cur_char  = RB_StrDup(cur_char);
  1347.     *end_char = old_char;
  1348.     return (cur_char);
  1349.   }
  1350.   return(NULL);
  1351. }
  1352.  
  1353. /*** RB_Find_Header_Name ***/
  1354.  
  1355.  
  1356. /****** RoboDoc.c/RB_Find_Item [3.0b]
  1357.  * NAME
  1358.  *   RB_Find_Item -- find item in header contents.
  1359.  * SYNOPSIS
  1360.  *   item_type = RB_Find_Item (next_line,item_line)
  1361.  *
  1362.  *           int RB_Find_Item (char **,  char **)
  1363.  * FUNCTION
  1364.  *   Searches the header contents line by line, looking
  1365.  *   for an item Indicator.
  1366.  * INPUTS
  1367.  *   next_line  - pointer to a pointer that points to line
  1368.  *                at which the search will start.
  1369.  * SIDE-EFFECTS
  1370.  *   next_line  - pointer to a pointer that points to begin of the line
  1371.  *                after the line the item was found on.
  1372.  *   item_line  - pointer to a pointer that points to the line the item
  1373.  *                was found on.
  1374.  * RESULT
  1375.  *   item_type  - one of possible items indicators.
  1376.  * SOURCE
  1377.  */
  1378.  
  1379. int RB_Find_Item (char **next_line,char **item_line)
  1380. {
  1381.   char *cur_char = *next_line ;
  1382.   int item_type ;
  1383.  
  1384.   for(item_type = NO_ITEM;
  1385.       *cur_char && (item_type == NO_ITEM);
  1386.      )
  1387.   {
  1388.     *item_line = cur_char ;
  1389.     cur_char = RB_Skip_Remark_Marker (cur_char) ;
  1390.  
  1391.     skip_while (isspace(*cur_char) && *cur_char != '\n') ;
  1392.     if (isupper(*cur_char))
  1393.     {
  1394.       char *item_begin = cur_char ;
  1395.       char *item_end ;
  1396.  
  1397.       skip_while (isupper(*cur_char)) ;
  1398.       item_end = cur_char ;
  1399.       if (isspace(*cur_char) && *cur_char)
  1400.       {
  1401.         skip_while (isspace(*cur_char) && *cur_char != '\n') ;
  1402.  
  1403.         /* Item consists of two words ? */
  1404.         if (isupper(*cur_char) && *cur_char)
  1405.         {
  1406.           skip_while (isupper(*cur_char)) ;
  1407.           item_end = cur_char ;
  1408.           skip_while (isspace(*cur_char) && *cur_char != '\n') ;
  1409.         }
  1410.         if (*cur_char == '\n')
  1411.         {
  1412.           char old_char = *item_end ;
  1413.  
  1414.           *item_end = '\0' ;
  1415.           item_type = RB_Get_Item_Type(item_begin);
  1416.           *item_end = old_char ;
  1417.           cur_char++ ;
  1418.         }
  1419.       }
  1420.     }
  1421.     if (item_type == NO_ITEM)
  1422.     {
  1423.       find_eol ; if (*cur_char) cur_char++ ;
  1424.     }
  1425.   }
  1426.  
  1427.   /* advance item_line to end of comment block when we have no more items */
  1428.   if (item_type == NO_ITEM) {
  1429.     *item_line = cur_char ;
  1430.   }
  1431.  
  1432.   *next_line = cur_char ;
  1433.   return item_type ;
  1434. }
  1435.  
  1436. /*** RB_Find_Item ***/
  1437.  
  1438.  
  1439. /****** RoboDoc.c/RB_Generate_xrefs [2.0]
  1440.  * NAME
  1441.  *   RB_Generate_xrefs
  1442.  * SYNOPSIS
  1443.  *   RB_Generate_xrefs (dest_doc, source_name, dest_name)
  1444.  *
  1445.  *   RB_Generate_xrefs (FILE *, char *, char *)
  1446.  * FUNCTION
  1447.  *   Generates a xref file for the document that has been
  1448.  *   analysed by robodoc.
  1449.  * INPUTS
  1450.  *   dest_doc    - pointer to the file to which the xrefs will be
  1451.  *                 written.
  1452.  *   source_name - pointer to the name of the document that has
  1453.  *                 been analysed by robodoc
  1454.  *   dest_name   - pointer to the name of the document robodoc will
  1455.  *                 write the documentation to.
  1456.  *   first_header - global variable, the list with function
  1457.  *                 headers.
  1458.  * SEE ALSO
  1459.  * SOURCE
  1460.  */
  1461.  
  1462. void RB_Generate_xrefs(FILE * dest_doc, char *source_name, char *dest_name)
  1463. {
  1464.   struct RB_header *cur_header;
  1465.  
  1466.   fprintf(dest_doc, "/* XREF-File generated by RoboDoc v"RB_VERSION" */\n");
  1467.   fprintf(dest_doc, "\nXREF:\n");
  1468.   fprintf(dest_doc, " \"%s\" \"%s\" 0 0\n", source_name, dest_name);
  1469.   for (cur_header = first_header;
  1470.        cur_header;
  1471.        cur_header = cur_header->next_header
  1472.     )
  1473.   {
  1474.     if (cur_header->function_name)
  1475.       fprintf(dest_doc, " \"%s\" \"%s\" 0 0\n",
  1476.               cur_header->function_name, dest_name);
  1477.   }
  1478.   fprintf(dest_doc, "\n/* End of XREF-File */\n");
  1479. }
  1480.  
  1481. /*** RB_Generate_xrefs ***/
  1482.  
  1483.  
  1484. /****** RoboDoc.c/RB_Generate_Documentation [3.0h]
  1485.  * NAME
  1486.  *   RB_Generate_Documentation
  1487.  * SYNOPSIS
  1488.  *   RB_Generate_Documentation (dest_doc, name, name)
  1489.  *
  1490.  *   RB_Generate_Documentation (FILE *, char *, char *)
  1491.  * FUNCTION
  1492.  *   Generates the autodoc documentation from the list of
  1493.  *   function headers that has been created by
  1494.  *   RB_Analyse_Document.
  1495.  * INPUTS
  1496.  *   dest_doc   - Pointer to the file to which the output will be written.
  1497.  *   src_name   - The name of the source file.
  1498.  *   dest_name  - The name of this file.
  1499.  * BUGS
  1500.  *   There might be plenty.
  1501.  * SEE ALSO
  1502.  *   RB_Generate_Doc_Start,
  1503.  *   RB_Generate_Doc_End,
  1504.  *   RB_Generate_Header_Start,
  1505.  *   RB_Generate_Header_End,
  1506.  *   RB_Generate_Header_Name,
  1507.  *   RB_Generate_Item_Name,
  1508.  *   RB_Generate_Item_Doc,
  1509.  *   RB_Generate_Item_Body.
  1510.  * SOURCE
  1511.  */
  1512.  
  1513. void RB_Generate_Documentation(FILE * dest_doc, char *src_name, char *dest_name)
  1514. {
  1515.   struct RB_header *cur_header;
  1516.  
  1517.   RB_Make_Index_Tables () ;
  1518.  
  1519.   RB_Generate_Doc_Start(dest_doc, src_name, dest_name) ;
  1520.  
  1521.   for (cur_header = first_header; cur_header; cur_header = cur_header->next_header)
  1522.   {
  1523.     int   item_type;
  1524.     char *next_line, *item_line = NULL;
  1525.  
  1526.     RB_Say("generating documentation for \"%s\"\n", cur_header->name);
  1527.  
  1528.     RB_Generate_Header_Start(    dest_doc, cur_header);
  1529. /*  RB_Generate_Header_Name(dest_doc, cur_header->name); */
  1530.  
  1531.     next_line = cur_header->contents;
  1532.     item_type = RB_Find_Item(&next_line, &item_line);
  1533.  
  1534.     if (item_type != NO_ITEM)
  1535.     {
  1536.       int   old_item_type;
  1537.       char *old_next_line;
  1538.  
  1539.       do {
  1540.         if (course_of_action & DO_TELL)
  1541.           printf("[%s] ", item_names[item_type]);
  1542.  
  1543.         RB_Generate_Item_Name(dest_doc, item_type);
  1544.  
  1545.         old_next_line = next_line;
  1546.         old_item_type = item_type;
  1547.  
  1548.         item_type = RB_Find_Item(&next_line, &item_line);
  1549.  
  1550.         RB_Generate_Item_Doc(dest_doc, dest_name,
  1551.                              old_next_line, item_line,
  1552.                              cur_header->function_name, old_item_type);
  1553.       } while(item_type != NO_ITEM);
  1554.       if (course_of_action & DO_TELL) putchar('\n') ;
  1555.     }
  1556.     else
  1557.       printf("%s: WARNING, header \"%s\" has no items\n", whoami, cur_header->name);
  1558.  
  1559.     RB_Generate_Header_End(dest_doc, cur_header);
  1560.   }
  1561.   RB_Generate_Doc_End(dest_doc, dest_name);
  1562. }
  1563.  
  1564. /*** RB_Generate_Documentation ***/
  1565.  
  1566.  
  1567. /****** RoboDoc.c/RB_Generate_Doc_Start [3.0j]
  1568.  * NAME
  1569.  *   RB_Generate_Doc_Start -- Generate document header.
  1570.  * SYNOPSIS
  1571.  *   RB_Generate_Doc_Start (dest_doc, src_name, name)
  1572.  *
  1573.  *   RB_Generate_Doc_Start (FILE *, char *, char *)
  1574.  * FUNCTION
  1575.  *   Generates for depending on the output_mode the text that
  1576.  *   will be at the start of a document.
  1577.  *   Including the table of contents.
  1578.  * INPUTS
  1579.  *   dest_doc - pointer to the file to which the output will
  1580.  *              be written.
  1581.  *   src_name - the name of the source file.
  1582.  *   name     - the name of this file.
  1583.  *   output_mode - global variable that indicates the output
  1584.  *                 mode.
  1585.  * SEE ALSO
  1586.  *   RB_Generate_Doc_End
  1587.  * SOURCE
  1588.  */
  1589.  
  1590. void RB_Generate_Doc_Start(FILE * dest_doc, char *src_name, char *name)
  1591. {
  1592.   struct  RB_header *cur_header;
  1593.   int     cur_len, max_len, header_nr;
  1594.  
  1595.   switch(output_mode)
  1596.   {
  1597.     case  AMIGAGUIDE:
  1598.       if (strstr(name + 1, ".guide") == NULL)
  1599.         fprintf(dest_doc, "@database %s.guide\n", name);
  1600.       else
  1601.         fprintf(dest_doc, "@database %s\n", name);
  1602.       fprintf(dest_doc, "@rem Source: %s\n", src_name);
  1603.       fprintf(dest_doc, "@rem " COMMENT_ROBODOC);
  1604.       fprintf(dest_doc, "@rem " COMMENT_COPYRIGHT);
  1605.       fprintf(dest_doc, "@node Main %s\n", name);
  1606.       fprintf(dest_doc, "@{jcenter}\n");
  1607.       fprintf(dest_doc, "@{fg highlight}@{b}TABLE OF CONTENTS@{ub}@{fg text}\n\n");
  1608.  
  1609.       max_len = 0;
  1610.       for (cur_header = first_header;
  1611.            cur_header;
  1612.            cur_header = cur_header->next_header)
  1613.       {
  1614.         if (cur_header->name)
  1615.         {
  1616.           cur_len = strlen(cur_header->name);
  1617.           if (cur_len > max_len)  max_len = cur_len;
  1618.         }
  1619.       }
  1620.  
  1621.       for (cur_header = first_header;
  1622.            cur_header;
  1623.            cur_header = cur_header->next_header)
  1624.       {
  1625.         if (cur_header->name && cur_header->function_name)
  1626.         {
  1627.           fprintf(dest_doc, "@{\"%s", cur_header->name);
  1628.  
  1629.           for (cur_len = strlen(cur_header->name);
  1630.                cur_len < max_len;
  1631.                ++cur_len) fputc(' ', dest_doc);
  1632.             fprintf(dest_doc, "\" Link \"%s\"}\n", cur_header->function_name);
  1633.         }
  1634.       }
  1635.  
  1636.       fprintf(dest_doc, "@{jleft}\n");
  1637.       fprintf(dest_doc, "@endnode\n");
  1638.       break;
  1639.  
  1640.     case HTML:
  1641.       /* Append document type and title */
  1642.       fprintf(dest_doc, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
  1643.       fprintf(dest_doc, "<HTML><HEAD>\n<TITLE>%s</TITLE>\n", name);
  1644.  
  1645.       /* append SGML-comment with document- and copyright-info. This code
  1646.        * ensures that every line has an own comment to avoid problems
  1647.        * with buggy browsers */
  1648.       fprintf(dest_doc, "<!-- Source: %s -->\n", src_name);
  1649.       {
  1650.         static const char copyright_text[] = COMMENT_ROBODOC COMMENT_COPYRIGHT;
  1651.         size_t i = 0;
  1652.         char previous_char = '\n';
  1653.         char current_char = copyright_text[i];
  1654.  
  1655.         while (current_char)
  1656.         {
  1657.             if (previous_char == '\n')
  1658.             {
  1659.                 fprintf(dest_doc, "<!-- ");
  1660.             }
  1661.  
  1662.             if (current_char == '\n')
  1663.             {
  1664.               fprintf(dest_doc, " -->");
  1665.             }
  1666.             else if ((current_char == '-') && (previous_char == '-'))
  1667.             {
  1668.                 /* avoid "--" inside SGML-comment, and use "-_" instead;
  1669.                  * this looks a bit strange, but one should still be
  1670.                  * able to figure out what is meant when reading the
  1671.                  * output */
  1672.                 current_char = '_';
  1673.             }
  1674.  
  1675.             fputc(current_char, dest_doc);
  1676.             i += 1;
  1677.             previous_char = current_char;
  1678.             current_char = copyright_text[i];
  1679.         }
  1680.       }
  1681.  
  1682.       /* append heading and start list of links to functions */
  1683.       fprintf(dest_doc, "</HEAD><BODY>\n");
  1684.       fprintf(dest_doc, "<H1 ALIGN=\"center\">TABLE OF CONTENTS</H1>\n");
  1685.       fprintf(dest_doc, "<OL>\n");
  1686.  
  1687.       for (cur_header = first_header;
  1688.            cur_header;
  1689.            cur_header = cur_header->next_header)
  1690.       {
  1691.         if (cur_header->name && cur_header->function_name)
  1692.           fprintf(dest_doc, "<LI><A HREF=\"#%s\">%s</A>\n",
  1693.                   cur_header->function_name, cur_header->name);
  1694.       }
  1695.       fprintf(dest_doc, "</OL>\n");
  1696.       break;
  1697.  
  1698.     case LATEX:
  1699.       fprintf(dest_doc, "%% Document: %s\n", name);
  1700.       fprintf(dest_doc, "%% Source: %s\n", src_name);
  1701.       fprintf(dest_doc, "%% " COMMENT_ROBODOC);
  1702.       fprintf(dest_doc, "%% " COMMENT_COPYRIGHT);
  1703.       fprintf(dest_doc, "\\documentstyle{article}\n");
  1704.       fprintf(dest_doc, "\\setlength{\\topmargin}{0in}\n");
  1705.       fprintf(dest_doc, "\\setlength{\\textwidth}{6.5in}\n");
  1706.       fprintf(dest_doc, "\\setlength{\\parindent}{0in}\n");
  1707.       fprintf(dest_doc, "\\setlength{\\parskip}{.08in}\n\n");
  1708.  
  1709.       /* changed default header to use boldface (vs slant) */
  1710.       fprintf(dest_doc, "\\pagestyle{myheadings}\n");
  1711.       fprintf(dest_doc, "\\markright{\\bf \\protect\\thesection \\hskip 1em"
  1712.                         "\\relax API Reference}\n\n");
  1713.  
  1714.       fprintf(dest_doc, "\\begin{document}\n");
  1715.       fprintf(dest_doc, "\\section{API Reference}\n"
  1716.                         "This section is your complete reference to the "
  1717.                         "functions and concepts for this system.\n");
  1718.  
  1719.       /* autogenerate table of contents! */
  1720.       fprintf(dest_doc, "\\tableofcontents\n");
  1721.       fprintf(dest_doc, "\\newpage\n");
  1722.  
  1723.       /* trick to disable the autogenerated \newpage */
  1724.       fputc('%', dest_doc);
  1725.       break;
  1726.  
  1727.     case RTF:
  1728.       {
  1729.         char *cook_link;
  1730.  
  1731.         /* RTF header */
  1732.         fprintf(dest_doc, "{\\rtf1\\ansi \\deff0"
  1733.                               "{\\fonttbl;"
  1734.                                   "\\f0\\fswiss MS Sans Serif;"
  1735.                                   "\\f1\\fmodern Courier New;"
  1736.                                   "\\f2\\ftech Symbol;"
  1737.                               "}"
  1738.                               "{\\colortbl;"
  1739.                                   "\\red255\\green255\\blue255;"
  1740.                                   "\\red0\\green0\\blue0;"
  1741.                                   "\\red0\\green0\\blue255;"
  1742.                               "}");
  1743.  
  1744.         /* RTF document info */
  1745.         fprintf(dest_doc,     "{\\info"
  1746.                                   "{\\title %s}"
  1747.                                   "{\\comment\n"
  1748.                                   " Source: %s\n"
  1749.                                   " " COMMENT_ROBODOC
  1750.                                   " " COMMENT_COPYRIGHT
  1751.                                   "}"
  1752.                               "}", name, src_name);
  1753.  
  1754.         /* RTF document format */
  1755.         fprintf(dest_doc, "{\\margl1440\\margr1440}\n");
  1756.  
  1757.         /* RTF document section */
  1758.         fprintf(dest_doc, "\\f0\\cb1\\cf3\\fs28\\b1\\qc" 
  1759.                           "{\\super #{\\footnote{\\super #}%s_TOC}}"
  1760.                           "{\\super ${\\footnote{\\super $}Contents}}"
  1761.                           "{TABLE OF CONTENTS}\\ql\\b0\\fs20\\cf2\\par\n", src_name);
  1762.         for (cur_header = first_header;
  1763.              cur_header;
  1764.              cur_header = cur_header->next_header)
  1765.         {
  1766.           if (cur_header->name && cur_header->function_name) {
  1767.             cook_link = RB_CookStr(cur_header->function_name);
  1768.             fprintf(dest_doc, "{\\uldb %s}{\\v %s}\\line\n",
  1769.                    cur_header->name, cook_link);
  1770.             free(cook_link);
  1771.           }
  1772.         }
  1773.         fprintf(dest_doc, "\\par\n");
  1774.       }
  1775.       break;
  1776.     case ASCII:
  1777.       if (course_of_action & DO_TOC)
  1778.       {
  1779.         fprintf(dest_doc, "TABLE OF CONTENTS\n");
  1780.         for (cur_header = first_header, header_nr = 1;
  1781.              cur_header;
  1782.              cur_header = cur_header->next_header, header_nr++)
  1783.         {
  1784.           if (cur_header->name && cur_header->function_name)
  1785.           {
  1786.             fprintf(dest_doc, "%4.4d %s\n", header_nr, cur_header->name);
  1787.           }
  1788.         }
  1789.         fputc('\f', dest_doc);
  1790.       }
  1791.  
  1792.     default: break;
  1793.   }
  1794. }
  1795.  
  1796. /*** RB_Generate_Doc_Start ***/
  1797.  
  1798.  
  1799. /****** RoboDoc.c/RB_Generate_Doc_End [3.0h]
  1800.  * NAME
  1801.  *   RB_Generate_Doc_End -- generate document trailer.
  1802.  * SYNOPSIS
  1803.  *   RB_Generate_Doc_End (dest_doc, name)
  1804.  *
  1805.  *   RB_Generate_Doc_End (FILE *, char *)
  1806.  * FUNCTION
  1807.  *   Generates for depending on the output_mode the text that
  1808.  *   will be at the end of a document.
  1809.  * INPUTS
  1810.  *   dest_doc - pointer to the file to which the output will
  1811.  *              be written.
  1812.  *   name     - the name of this file.
  1813.  *   output_mode - global variable that indicates the output
  1814.  *                 mode.
  1815.  * NOTES
  1816.  *   Doesn't do anything with its arguments, but that might
  1817.  *   change in the future.
  1818.  * BUGS
  1819.  * SOURCE
  1820.  */
  1821.  
  1822. void RB_Generate_Doc_End(FILE * dest_doc, char *name)
  1823. {
  1824.   switch(output_mode)
  1825.   {
  1826.     case AMIGAGUIDE: fputc('\n', dest_doc); break;
  1827.     case HTML:  fprintf(dest_doc, "</BODY></HTML>\n"); break;
  1828.     case LATEX: fprintf(dest_doc, "\\end{document}\n"); break;
  1829.     case RTF:   fputc('}', dest_doc); break ;
  1830.     case ASCII: break ;
  1831.   }
  1832. }
  1833.  
  1834. /*** RB_Generate_Doc_End ***/
  1835.  
  1836.  
  1837. /****** RoboDoc.c/RB_Generate_Header_Start [3.0h]
  1838.  * NAME
  1839.  *   RB_Generate_Header_Start -- generate header start text.
  1840.  * SYNOPSIS
  1841.  *  void RB_Generate_Header_Start (dest_doc, cur_header)
  1842.  *
  1843.  *  void RB_Generate_Header_Start (FILE *, struct RB_header *)
  1844.  * FUNCTION
  1845.  *   Generates depending on the output_mode the text that
  1846.  *   will be at the end of each header.
  1847.  * INPUTS
  1848.  *   dest_doc - pointer to the file to which the output will
  1849.  *              be written.
  1850.  *   cur_header - pointer to a RB_header structure.
  1851.  * SEE ALSO
  1852.  *   RB_Generate_Header_End
  1853.  * SOURCE
  1854.  */
  1855.  
  1856. void RB_Generate_Header_Start (FILE * dest_doc, struct RB_header *cur_header)
  1857. {
  1858.   char *cook_link;
  1859.  
  1860.   switch(output_mode)        /* switch by *koessi*/
  1861.   {
  1862.     case AMIGAGUIDE:
  1863.       if (cur_header->name && cur_header->function_name)
  1864.       {
  1865.         fprintf(dest_doc, "@Node \"%s\" \"%s\"\n",
  1866.                 cur_header->function_name,
  1867.                 cur_header->name);
  1868.         fprintf(dest_doc, "%s", att_start_command[MAKE_SHINE][output_mode]);
  1869.         fprintf(dest_doc, "%s", cur_header->name);
  1870.         fprintf(dest_doc, "%s", att_stop_command[MAKE_SHINE][output_mode]);
  1871.         fprintf(dest_doc, "\n\n") ;
  1872.       }
  1873.       break;
  1874.     case HTML:
  1875.       if (cur_header->name && cur_header->function_name)
  1876.       {
  1877.         fprintf(dest_doc, "<HR>\n");
  1878.         fprintf(dest_doc, "\n<H2><A NAME=\"%s\">%s</A></H2>\n\n",
  1879.                 cur_header->function_name,
  1880.                 cur_header->name);
  1881.       }
  1882.       break;
  1883.     case LATEX:
  1884.       cook_link = RB_CookStr(cur_header->name);
  1885.       fprintf(dest_doc, "\\newpage\n");
  1886.       fprintf(dest_doc, "\\subsection{%s}\n", cook_link);
  1887.       free(cook_link);
  1888.       break;
  1889.     case RTF:
  1890.       if (cur_header->name && cur_header->function_name)
  1891.       {
  1892.         cook_link = RB_CookStr(cur_header->function_name);
  1893.         fprintf(dest_doc, "\\page"
  1894.                 "{\\super #{\\footnote{\\super #}%s}}"
  1895.                 "{\\super ${\\footnote{\\super $}%s}}"
  1896.                 "\\cf3 %s\\cf2\\line\n",
  1897.                 cur_header->function_name,
  1898.                 cur_header->name,
  1899.                 cur_header->name);
  1900.         free(cook_link);
  1901.       }
  1902.       break;
  1903.     case ASCII:
  1904.       {
  1905.         fprintf(dest_doc, "%s", att_start_command[MAKE_SHINE][output_mode]);
  1906.         fprintf(dest_doc, "%s", cur_header->name);
  1907.         fprintf(dest_doc, "%s", att_stop_command[MAKE_SHINE][output_mode]);
  1908.         fprintf(dest_doc, "\n\n") ;
  1909.       }
  1910.       break;
  1911.   }
  1912. }
  1913.  
  1914. /*** RB_Generate_Header_Start ***/
  1915.  
  1916.  
  1917. /****** RoboDoc.c/RB_Generate_Header_End [3.0h]
  1918.  * NAME
  1919.  *   RB_Generate_Header_End
  1920.  * SYNOPSIS
  1921.  *   void RB_Generate_Header_End (dest_doc, cur_header)
  1922.  *
  1923.  *   void RB_Generate_Header_End (FILE *, struct RB_header *)
  1924.  * FUNCTION
  1925.  *   Generates for depending on the output_mode the text that
  1926.  *   will be at the end of a header.
  1927.  * INPUTS
  1928.  *   dest_doc - pointer to the file to which the output will
  1929.  *              be written.
  1930.  *   cur_header - pointer to a RB_header structure.
  1931.  * SEE ALSO
  1932.  *   RB_Generate_Header_Start
  1933.  * SOURCE
  1934.  */
  1935.  
  1936. void RB_Generate_Header_End (FILE * dest_doc, struct RB_header *cur_header)
  1937. {
  1938.   switch(output_mode)        /* switch by *koessi*/
  1939.   {
  1940.     case AMIGAGUIDE:
  1941.       if (cur_header->name && cur_header->function_name)
  1942.         fprintf(dest_doc, "@endnode\n");
  1943.       break;
  1944.     case HTML:
  1945.     case LATEX: fputc('\n', dest_doc); break;
  1946.     case RTF:   fprintf(dest_doc, "\\par\n"); break;
  1947.     case ASCII: fputc('\f', dest_doc);
  1948.     default:  break;
  1949.   }
  1950. }
  1951.  
  1952. /*** RB_Generate_Header_End ***/
  1953.  
  1954.  
  1955. /****** RoboDoc.c/RB_Generate_Header_Name [3.0c]
  1956.  * NAME
  1957.  *   RB_Generate_Header_Name
  1958.  * SYNOPSIS
  1959.  *   RB_Generate_Header_Name (dest_doc, name)
  1960.  *
  1961.  *   RB_Generate_Header_Name (FILE *, char *)
  1962.  * INPUTS
  1963.  *  dest_doc - pointer to the file to which the output will
  1964.  *             be written.
  1965.  *  name - pointer to the header name.
  1966.  * SOURCE
  1967.  */
  1968.  
  1969. void RB_Generate_Header_Name(FILE * dest_doc, char *name)
  1970. {
  1971.   char format_str[] = "%s";
  1972.   fprintf(dest_doc, format_str, att_start_command[MAKE_SHINE][output_mode]);
  1973.   fprintf(dest_doc, format_str, name);
  1974.   fprintf(dest_doc, format_str, att_stop_command[MAKE_SHINE][output_mode]);
  1975.   fprintf(dest_doc, "\n\n");
  1976. }
  1977.  
  1978. /*** RB_Generate_Header_Name ***/
  1979.  
  1980.  
  1981. /****** RoboDoc.c/RB_Generate_Item_Name [2.01]
  1982.  * NAME
  1983.  *   RB_Generate_Item_Name -- fast&easy
  1984.  * SYNOPSIS
  1985.  *   void RB_Generate_Item_Name( FILE * dest_doc, int item_type )
  1986.  * FUNCTION
  1987.  *   write the items name to the doc
  1988.  * INPUTS
  1989.  *   FILE * dest_doc         -- document in progress
  1990.  *   int item_type           -- this leads to the name and makes colors
  1991.  * AUTHOR
  1992.  *   Koessi
  1993.  * NOTES
  1994.  *   uses globals: output_mode, item_names[]
  1995.  * SOURCE
  1996.  */
  1997.  
  1998. void RB_Generate_Item_Name(FILE * dest_doc, int item_type)
  1999. {
  2000.   char format_str[] = "%s";
  2001.  
  2002.   if (item_attributes[item_type] & ITEM_NAME_LARGE_FONT)
  2003.   {
  2004.     fprintf(dest_doc, format_str, att_start_command[MAKE_LARGE][output_mode]);
  2005.     fprintf(dest_doc, format_str, item_names[item_type]);
  2006.     fprintf(dest_doc, format_str, att_stop_command[ MAKE_LARGE][output_mode]);
  2007.   }
  2008.   else fprintf(dest_doc, format_str, item_names[item_type]);
  2009.  
  2010.   fputc('\n', dest_doc);
  2011. }
  2012.  
  2013. /*** RB_Generate_Item_Name *** Zitatende ***/
  2014.  
  2015.  
  2016. /****** RoboDoc.c/RB_Generate_Item_Doc [3.0j]
  2017.  * NAME
  2018.  *   RB_Generate_Item_Doc
  2019.  * SYNOPSIS
  2020.  *   void RB_Generate_Item_Doc(FILE * dest_doc, char *dest_name,
  2021.  *                             char *begin_of_item,
  2022.  *                             char *end_of_item,
  2023.  *                             char *function_name,
  2024.  *                             int item_type)
  2025.  * FUNCTION
  2026.  *   Generates the body text of an item, applying predefined attributes
  2027.  *   to the text.
  2028.  * NOTES
  2029.  *   Body text is always non-proportional for several reasons:
  2030.  *   1) text is rarely written with prop spacing and text wrapping
  2031.  *      in mind -- e.g., see SYNOPSIS above
  2032.  *   2) source code looks better
  2033.  *   3) it simplifies LaTeX handling
  2034.  * SOURCE
  2035.  */
  2036.  
  2037. void RB_Generate_Item_Doc(FILE * dest_doc, char *dest_name,
  2038.                           char *begin_of_item,
  2039.                           char *end_of_item,
  2040.                           char *function_name,
  2041.                           int item_type)
  2042. {
  2043.   char format_str[] = "%s";
  2044.  
  2045.   if (begin_of_item == end_of_item)
  2046.   {
  2047.     switch (output_mode)
  2048.     {
  2049.       case HTML:
  2050.         fprintf(dest_doc, "<BR>\n"); break;
  2051.       case LATEX:
  2052.         fprintf(dest_doc, "\\\\\n"); break;
  2053.       case RTF:
  2054.         fprintf(dest_doc, "\n"); break;
  2055.       default:
  2056.         break;
  2057.     }
  2058.     return;
  2059.   }
  2060.  
  2061.   /* For text body in HTML, change to non-prop _before_ changing font style.
  2062.    * To conform to DTD, this avoids <B><PRE> and instead uses <PRE><B> */
  2063.   if (output_mode == HTML)
  2064.   {
  2065.     fprintf(dest_doc, "<PRE>");
  2066.   }
  2067.  
  2068.   /* change font style */
  2069.   if (item_attributes[item_type] & TEXT_BODY_LARGE_FONT)
  2070.     fprintf(dest_doc, format_str, att_start_command[MAKE_LARGE][output_mode]);
  2071.   if (item_attributes[item_type] & TEXT_BODY_ITALICS)
  2072.     fprintf(dest_doc, format_str, att_start_command[MAKE_ITALICS][output_mode]);
  2073.   if (item_attributes[item_type] & TEXT_BODY_NON_PROP)
  2074.     fprintf(dest_doc, format_str, att_start_command[MAKE_NON_PROP][output_mode]);
  2075.   if (item_attributes[item_type] & TEXT_BODY_SMALL_FONT)
  2076.     fprintf(dest_doc, format_str, att_start_command[MAKE_SMALL][output_mode]);
  2077.   if (item_attributes[item_type] & TEXT_BODY_BOLD)
  2078.     fprintf(dest_doc, format_str, att_start_command[MAKE_BOLD][output_mode]);
  2079.   if (item_attributes[item_type] & TEXT_BODY_UNDERLINE)
  2080.     fprintf(dest_doc, format_str, att_start_command[MAKE_UNDERLINE][output_mode]);
  2081.   if (item_attributes[item_type] & TEXT_BODY_SHINE)
  2082.     fprintf(dest_doc, format_str, att_start_command[MAKE_SHINE][output_mode]);
  2083.  
  2084.   /*
  2085.    * For some modes, the text body is always non-prop
  2086.    */
  2087.   switch (output_mode) {
  2088.     case LATEX:
  2089.       fprintf(dest_doc, "\\begin{verbatim}\n"); break;
  2090.     case RTF:
  2091.       fprintf(dest_doc, "{\\f1{}"); break;
  2092.     default:
  2093.       break;
  2094.   }
  2095.  
  2096.   RB_Generate_Item_Body(dest_doc, dest_name, begin_of_item, end_of_item,
  2097.                           function_name, item_type);
  2098.  
  2099.   switch (output_mode) {
  2100.     case LATEX:
  2101.       /* split the text so LaTeX doesn't get confused ;) */
  2102.       fprintf(dest_doc, "\\" "end{verbatim}\n"); break;
  2103.     case RTF:
  2104.       fputc('}', dest_doc);
  2105.     default:
  2106.       break;
  2107.   }
  2108.  
  2109.   /* restore font style */
  2110.   if (item_attributes[item_type] & TEXT_BODY_SHINE)
  2111.     fprintf(dest_doc, format_str, att_stop_command[MAKE_SHINE][output_mode]);
  2112.   if (item_attributes[item_type] & TEXT_BODY_UNDERLINE)
  2113.     fprintf(dest_doc, format_str, att_stop_command[MAKE_UNDERLINE][output_mode]);
  2114.   if (item_attributes[item_type] & TEXT_BODY_BOLD)
  2115.     fprintf(dest_doc, format_str, att_stop_command[MAKE_BOLD][output_mode]);
  2116.   if (item_attributes[item_type] & TEXT_BODY_SMALL_FONT)
  2117.     fprintf(dest_doc, format_str, att_stop_command[MAKE_SMALL][output_mode]);
  2118.   if (item_attributes[item_type] & TEXT_BODY_NON_PROP)
  2119.     fprintf(dest_doc, format_str, att_stop_command[MAKE_NON_PROP][output_mode]);
  2120.   if (item_attributes[item_type] & TEXT_BODY_ITALICS)
  2121.     fprintf(dest_doc, format_str, att_stop_command[MAKE_ITALICS][output_mode]);
  2122.   if (item_attributes[item_type] & TEXT_BODY_LARGE_FONT)
  2123.     fprintf(dest_doc, format_str, att_stop_command[MAKE_LARGE][output_mode]);
  2124.  
  2125.   if (output_mode != HTML)
  2126.   {
  2127.     fputc('\n', dest_doc);
  2128.   }
  2129.  
  2130.   /* for HTML, switch back to prop-font after restoring font style */
  2131.   if (output_mode == HTML)
  2132.   {
  2133.     fprintf(dest_doc, "</PRE>");
  2134.   }
  2135.  
  2136. }
  2137.  
  2138. /*** RB_Generate_Item_Doc ***/
  2139.  
  2140.  
  2141. /****** RoboDoc.c/RB_Skip_Remark_Marker [2.0e]
  2142.  * NAME
  2143.  *    RB_Skip_Remark_Marker
  2144.  * SYNOPSIS
  2145.  *     text  = RB_Skip_Remark_Marker (line_buffer)
  2146.  *    char *                            char *
  2147.  * FUNCTION
  2148.  *    Scan and search for a recognized remark marker; skip past the
  2149.  *    marker to the body of the text
  2150.  ******/
  2151.  
  2152. char *RB_Skip_Remark_Marker (char *line_buffer)
  2153. {
  2154.   int marker, found ;
  2155.   char *cur_char, *cur_mchar ;
  2156.  
  2157.   found = FALSE ;
  2158.   for (marker=0 ;
  2159.        ((cur_mchar = remark_markers[marker]) != NULL) && !found ;
  2160.        marker++)
  2161.   {
  2162.     for (found = TRUE, cur_char = line_buffer;
  2163.          *cur_mchar && *cur_char && found;
  2164.           cur_mchar++, cur_char++)
  2165.     { if (*cur_mchar != *cur_char) found = FALSE ; }
  2166.   }
  2167.   return (cur_char) ;
  2168. }
  2169.  
  2170.  
  2171. /****** RoboDoc.c/RB_Generate_Item_Body [3.0h]
  2172.  * NAME
  2173.  *  RB_Generate_Item_Body
  2174.  * SYNOPSIS
  2175.  *  void RB_Generate_Item_Body(FILE * dest_doc, char *dest_name,
  2176.  *                             char *begin_of_item, char *end_of_item,
  2177.  *                             char *function_name,
  2178.  *                             int   item_type)
  2179.  *
  2180.  * FUNCTION
  2181.  *   Generates body of an item in output-specific form
  2182.  * INPUTS
  2183.  *   dest_doc      - pointer to the file to which
  2184.  *                   the output will be written.
  2185.  *   dest_name     - the name of this file.
  2186.  *   begin_of_item -
  2187.  *   end_of_item   -
  2188.  *   function_name -
  2189.  *   item_type     -
  2190.  * NOTES
  2191.  *   o almost completely rewritten by koessi
  2192.  *   o Almost completely Re-Rewritten by Slothouber :)
  2193.  * SOURCE
  2194.  */
  2195.  
  2196. void RB_Generate_Item_Body(FILE * dest_doc, char *dest_name,
  2197.                            char *begin_of_item, char *end_of_item,
  2198.                            char *function_name,
  2199.                            int   item_type)
  2200. {
  2201.   char *cur_char, old_char, c ;
  2202.  
  2203.   cur_char = begin_of_item;
  2204.  
  2205.   if (item_type == SOURCE_ITEM) {
  2206.     /* skip end_comment_marker */
  2207.     for (; *cur_char && *cur_char != '\n' ; cur_char++ )
  2208.       ;
  2209.  
  2210.     /* skip blank lines leading up to source code */
  2211.     while (*cur_char == '\n')
  2212.       cur_char++;
  2213.  
  2214.     /* trim blanks following source code */
  2215.     do {
  2216.       end_of_item--;
  2217.     } while (end_of_item > cur_char && isspace(*end_of_item));
  2218.     end_of_item++;  /* advance 1 for placement of the NUL */
  2219.   }
  2220.  
  2221.   old_char = *end_of_item;
  2222.   *end_of_item = '\0';
  2223.  
  2224.   for (; *cur_char; cur_char++)
  2225.   {
  2226.     int tb = tab_size;
  2227.     int do_search = TRUE ;
  2228.     int was_link  = FALSE;
  2229.  
  2230.     if (item_type != SOURCE_ITEM) {
  2231.       cur_char = RB_Skip_Remark_Marker(cur_char) ;
  2232.     } else {
  2233.       /* indent source */
  2234.       switch (output_mode) {
  2235.         case RTF:
  2236.           fprintf(dest_doc, "\\tab ");
  2237.           break;
  2238.  
  2239.         case AMIGAGUIDE:
  2240.         case HTML:
  2241.         case LATEX:
  2242.         default:
  2243.           fprintf(dest_doc, "    ");
  2244.       }
  2245.     }
  2246.  
  2247.     while (((c = *cur_char) != '\0') && (c != '\n'))
  2248.     {
  2249.       char *label_name, *file_name;
  2250.       int   tmp;
  2251.  
  2252.       if (!do_search)
  2253.       {
  2254.         if (!isalnum(c) && (c != '_'))
  2255.         {
  2256.           do_search = TRUE ;
  2257.         }
  2258.       }
  2259.       else
  2260.       {
  2261.         if (isalpha(c) || (c == '_'))
  2262.         {
  2263.           if ((was_link = RB_Find_Link(cur_char, &label_name, &file_name)) == FALSE)
  2264.           {
  2265.             do_search = FALSE ;
  2266.           }
  2267.         }
  2268.         else was_link = FALSE ;
  2269.       }
  2270.  
  2271.       if (!was_link)
  2272.       {
  2273.         switch(output_mode) {
  2274.           case AMIGAGUIDE:
  2275.             switch(c) {
  2276.               case '\n' : --cur_char; break;
  2277.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2278.                             fputc(' ', dest_doc) ;
  2279.                           break;
  2280.               case '@'  : fprintf(dest_doc, "\\@" );
  2281.                           tb++; break;
  2282.               case '\\' : fprintf(dest_doc, "\\\\") ;
  2283.                           tb++; break;
  2284.               default   : fputc(c, dest_doc); tb++;
  2285.             }
  2286.             break;
  2287.  
  2288.           case HTML:
  2289.             switch(c) {
  2290.               case '\n' : --cur_char; break;
  2291.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2292.                             fputc(' ', dest_doc) ;
  2293.                           break;
  2294.               case '<'  : fprintf(dest_doc, "<");
  2295.                           tb++; break;
  2296.               case '>'  : fprintf(dest_doc, ">");
  2297.                           tb++; break;
  2298.               case '&'  : fprintf(dest_doc, "&");
  2299.                           tb++; break;
  2300.               default   : fputc(c, dest_doc); tb++;
  2301.             }
  2302.             break;
  2303.  
  2304.           case LATEX:
  2305.             switch(c) {
  2306.               case '\n' : --cur_char; break;
  2307.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2308.                             fputc(' ', dest_doc) ;
  2309.                           break;
  2310. #if 0
  2311.               /* not used in LaTeX's verbatim environment */
  2312.               case '$'  :
  2313.               case '&'  :
  2314.               case '%'  :
  2315.               case '#'  :
  2316.               case '_'  :
  2317.               case '{'  :
  2318.               case '}'  : fputc('\\', dest_doc); fputc(c, dest_doc);
  2319.                           tb++; break;
  2320.               case '\\' : fprintf(dest_doc, "$\\backslash$");
  2321.                           tb++; break;
  2322.               case '~'  : fprintf(dest_doc, "$\\tilde$");
  2323.                           tb++; break;
  2324.               case '^'  : fprintf(dest_doc, "$\\,\\!^{\\sim}$");
  2325.                           tb++; break;
  2326. #endif
  2327.               default   : fputc(c, dest_doc); tb++;
  2328.             }
  2329.             break;
  2330.  
  2331.           case RTF:
  2332.             switch(c) {
  2333.               case '\n' : --cur_char; break;
  2334.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2335.                             fputc(' ', dest_doc) ;
  2336.                           break;
  2337.               case '\\' :
  2338.               case '{'  :
  2339.               case '}'  : fputc('\\', dest_doc); fputc(c, dest_doc);
  2340.                           tb++; break;
  2341.               default   : fputc(c, dest_doc); tb++;
  2342.             }
  2343.             break;
  2344.  
  2345.           default:
  2346.             fputc(c, dest_doc); tb++;
  2347.         }
  2348.         cur_char++;
  2349.       }
  2350.       else
  2351.       {
  2352.         switch(output_mode)
  2353.         {
  2354.           case AMIGAGUIDE :
  2355.             if (file_name && strcmp(file_name, dest_name))
  2356.                 fprintf(dest_doc,"@{\"%s\" Link \"%s/%s\"}",
  2357.                         label_name, file_name, label_name);
  2358.             else
  2359.             {
  2360.               if (strcmp(label_name, function_name))
  2361.                  fprintf(dest_doc,"@{\"%s\" Link \"%s\"}",
  2362.                          label_name, label_name) ;
  2363.               else
  2364.               {
  2365.                 fprintf(dest_doc,"%s",
  2366.                         att_start_command[MAKE_BOLD][output_mode]);
  2367.                 fprintf(dest_doc,"%s", label_name);
  2368.                 fprintf(dest_doc,"%s",
  2369.                         att_stop_command[MAKE_BOLD][output_mode]);
  2370.               }
  2371.             }
  2372.             break;
  2373.  
  2374.           case HTML :
  2375.             if (file_name && strcmp(file_name, dest_name))
  2376.             fprintf(dest_doc,"<A HREF=\"%s#%s\">%s</A>",
  2377.                     file_name, label_name, label_name);
  2378.             else
  2379.             {
  2380.               if (strcmp(label_name, function_name))
  2381.                   fprintf(dest_doc,"<A HREF=\"#%s\">%s</A>",
  2382.                           label_name, label_name);
  2383.               else
  2384.               {
  2385.                 fprintf(dest_doc,"%s",
  2386.                         att_start_command[MAKE_BOLD][output_mode]);
  2387.                 fprintf(dest_doc,"%s", label_name);
  2388.                 fprintf(dest_doc,"%s",
  2389.                         att_stop_command[MAKE_BOLD][output_mode]);
  2390.               }
  2391.             }
  2392.             break;
  2393.  
  2394.           case RTF :
  2395.             if (strcmp(label_name, function_name)) {
  2396.               char *cook_link;
  2397.  
  2398.               cook_link = RB_CookStr(label_name);
  2399.               fprintf(dest_doc, "{\\uldb %s}{\\v %s}",
  2400.                       label_name, cook_link);
  2401.               free(cook_link);
  2402.             } else {
  2403.               fprintf(dest_doc,"%s",
  2404.                       att_start_command[MAKE_BOLD][output_mode]);
  2405.               fprintf(dest_doc,"%s", label_name);
  2406.               fprintf(dest_doc,"%s",
  2407.                       att_stop_command[MAKE_BOLD][output_mode]);
  2408.             }
  2409.             break;
  2410.           default: fprintf(dest_doc,"%s", label_name) ;
  2411.         }
  2412.         tmp = strlen(label_name); cur_char += tmp; tb += tmp;
  2413.       } /* end if */
  2414.     }
  2415.  
  2416.     if (*cur_char) {
  2417.       if (output_mode == RTF)
  2418.         fprintf(dest_doc, "\\line");
  2419.       fputc('\n', dest_doc);
  2420.     }
  2421.   }
  2422.   *end_of_item = old_char;
  2423. }
  2424.  
  2425. /*** RB_Generate_Item_Body ***/
  2426.  
  2427.  
  2428. /****** RoboDoc.c/RB_Make_Index_Tables [3.0b]
  2429.  * NAME
  2430.  *    RB_Make_Index_Tables
  2431.  * SYNOPSIS
  2432.  *    void RB_Make_Index_Tables (void)
  2433.  * FUNCTION
  2434.  *    Creates sorted index tables of headers and links to speed up
  2435.  *    matching links later on.
  2436.  * INPUTS
  2437.  *    none
  2438.  * SIDE EFFECTS
  2439.  *    Modifies header_index & link_index
  2440.  * RESULT
  2441.  *    none
  2442.  ******/
  2443.  
  2444. void RB_Make_Index_Tables ()
  2445. {
  2446.   int nr_of_headers, header ;
  2447.   int nr_of_links, link ;
  2448.   struct RB_link    *cur_link;
  2449.   struct RB_header  *cur_header;
  2450.  
  2451.   for (cur_header = first_header, nr_of_headers = 0;
  2452.        cur_header;
  2453.        cur_header = cur_header->next_header) nr_of_headers++ ;
  2454.  
  2455.   for (cur_link = first_link, nr_of_links = 0;
  2456.        cur_link;
  2457.        cur_link = cur_link->next_link) nr_of_links++ ;
  2458.  
  2459.   if (nr_of_headers)
  2460.   {
  2461.     int sort1, sort2 ;
  2462.  
  2463.     RB_Say("Allocating Header Index Table\n");
  2464.     header_index = (struct RB_header **)malloc(nr_of_headers*sizeof(struct RB_header **)) ;
  2465.     header_index_size = nr_of_headers ;
  2466.     if (!header_index) RB_Panic ("out of memory! [Make Index Tables]\n") ;
  2467.  
  2468.     /* Fill Index Table */
  2469.     for (cur_header = first_header, header = 0;
  2470.           cur_header;
  2471.           cur_header = cur_header->next_header, header++)
  2472.         header_index[header] = cur_header ;
  2473.  
  2474.     /* Sort Index Table */
  2475.     RB_Say("Sorting Header Index Table\n");
  2476.     for (sort1 = 0; sort1 < nr_of_headers; sort1++)
  2477.     {
  2478.       struct RB_header *temp ;
  2479.       for (sort2 = sort1; sort2 < nr_of_headers; sort2++)
  2480.       {
  2481.         if (strcmp(header_index[sort1]->function_name,
  2482.                    header_index[sort2]->function_name) > 0)
  2483.         {
  2484.           temp = header_index[sort1] ;
  2485.           header_index[sort1] = header_index[sort2] ;
  2486.           header_index[sort2] = temp ;
  2487.         }
  2488.       }
  2489.     }
  2490.   }
  2491.  
  2492.   if (nr_of_links)
  2493.   {
  2494.     int sort1, sort2 ;
  2495.  
  2496.     RB_Say("Allocating Link Index Table\n");
  2497.     link_index   = (struct RB_link **)malloc(nr_of_links*sizeof(struct RB_link **)) ;
  2498.     link_index_size = nr_of_links ;
  2499.     if (!link_index) RB_Panic ("out of memory! [Make Index Tables]\n") ;
  2500.  
  2501.     /* Fill Index Table */
  2502.     for (cur_link = first_link, link = 0;
  2503.          cur_link;
  2504.          cur_link = cur_link->next_link, link++)
  2505.     {
  2506.       link_index[link] = cur_link ;
  2507.     }
  2508.  
  2509.     /* Sort Index Table */
  2510.     RB_Say("Sorting Link Index Table\n");
  2511.     for (sort1 = 0; sort1 < nr_of_links; sort1++)
  2512.     {
  2513.       struct RB_link *temp ;
  2514.       for (sort2 = sort1; sort2 < nr_of_links; sort2++)
  2515.       {
  2516.         if (strcmp(link_index[sort1]->label_name,
  2517.                    link_index[sort2]->label_name) > 0)
  2518.         {
  2519.           temp = link_index[sort1] ;
  2520.           link_index[sort1] = link_index[sort2] ;
  2521.           link_index[sort2] = temp ;
  2522.         }
  2523.       }
  2524.     }
  2525.   }
  2526. }
  2527.  
  2528.  
  2529. /****** RoboDoc.c/RB_Find_Link [3.0h]
  2530.  * NAME
  2531.  *   RB_Find_Link -- try to match word with a link
  2532.  * SYNOPSIS
  2533.  *   result = RB_Find_Link (word_begin, label_name, file_name)
  2534.  *   int      RB_Find_Link (char *,     char **,    char **)
  2535.  * FUNCTION
  2536.  *   Searches for the given word in the list of links.
  2537.  * INPUTS
  2538.  *   word_begin  - pointer to a word (a string).
  2539.  *   label_name  - pointer to a pointer to a string
  2540.  *   file_name   - pointer to a pointer to a string
  2541.  * SIDE EFFECTS
  2542.  *   label_name & file_name are modified
  2543.  * RESULT
  2544.  *   TRUE or FALSE.
  2545.  * NOTES
  2546.  *   re-rewritten by frans
  2547.  * BUGS
  2548.  * SOURCE
  2549.  */
  2550.  
  2551. int RB_Find_Link(char *word_begin, char **label_name, char **file_name)
  2552. {
  2553.   char  *cur_char, old_char ;
  2554.   int low_index, high_index, cur_index, state ;
  2555.  
  2556.   for (cur_char = word_begin ;
  2557.        isalnum(*cur_char) || (*cur_char == '_') || (*cur_char == '-')
  2558.        || (*cur_char == '.' && isalnum(*(cur_char+1))) ;
  2559.        cur_char++)
  2560.     ;
  2561.   old_char = *cur_char ;
  2562.   *cur_char = '\0' ;
  2563.  
  2564.   for (cur_index = 0, low_index = 0, high_index = header_index_size-1 ;
  2565.        high_index >= low_index ; )
  2566.   {
  2567.     cur_index = (high_index - low_index)/2 + low_index ;
  2568.     state = strcmp(word_begin, header_index[cur_index]->function_name) ;
  2569.     if (state < 0) high_index = cur_index-1 ;
  2570.     else if (state > 0) low_index = cur_index+1 ;
  2571.     else
  2572.     {
  2573.       *label_name = header_index[cur_index]->function_name ;
  2574.       *file_name  = NULL ;
  2575.       *cur_char   = old_char ;
  2576.  
  2577.       if (strlen(*label_name) > 60) RB_Panic ("Internal Error #1\n") ;
  2578.       return(TRUE) ;
  2579.     }
  2580.   }
  2581.  
  2582.   for (cur_index = 0, low_index = 0, high_index = link_index_size-1 ;
  2583.        high_index >= low_index ; )
  2584.   {
  2585.     cur_index = (high_index - low_index)/2 + low_index ;
  2586.     state = strcmp(word_begin, link_index[cur_index]->label_name) ;
  2587.     if (state < 0)
  2588.     {
  2589.       high_index = cur_index-1 ;
  2590.     }
  2591.     else if (state == 0)
  2592.     {
  2593.       *label_name = link_index[cur_index]->label_name ;
  2594.       *file_name  = link_index[cur_index]->file_name ;
  2595.       if (strlen(*label_name) > 60) RB_Panic ("Internal Error #2\n") ;
  2596.       if (strlen(*file_name) > 60)  RB_Panic ("Internal Error #3\n") ;
  2597.       *cur_char   = old_char ;
  2598.       return(TRUE) ;
  2599.     }
  2600.     else if (state > 0)
  2601.     {
  2602.       low_index = cur_index+1 ;
  2603.     }
  2604.   }
  2605.   *cur_char = old_char ;
  2606.   *file_name = NULL ;
  2607.   *label_name = NULL ;
  2608.   return(FALSE);
  2609. }
  2610.  
  2611. /*** RB_Find_Link ***/
  2612.  
  2613.  
  2614. /****** RoboDoc.c/RB_Slow_Sort [2.0]
  2615.  * NAME
  2616.  *   RB_Slow_Sort -- sort list of headers alphabetically
  2617.  * SYNOPSIS
  2618.  *   RB_Slow_Sort ()
  2619.  * FUNCTION
  2620.  *   Sorts the list of headers according to the header name
  2621.  *   in alphabetically fashion.
  2622.  * NOTES
  2623.  *   This isn't a particularly speedy way of sorting.
  2624.  * SOURCE
  2625.  */
  2626.  
  2627. void RB_Slow_Sort()
  2628. {
  2629.   struct RB_header *cur_header, *unsorted_headers, *bigger_header ;
  2630.  
  2631.   if ((unsorted_headers = first_header) != NULL)  /* additional check *koessi */
  2632.   {
  2633.     for (first_header = NULL;
  2634.          unsorted_headers->next_header; )
  2635.     {
  2636.       for (bigger_header = unsorted_headers,
  2637.            cur_header = bigger_header->next_header;
  2638.            cur_header;
  2639.            cur_header = cur_header->next_header)
  2640.       {
  2641.         if (strcmp(cur_header->name, bigger_header->name) > 0)
  2642.           bigger_header = cur_header;
  2643.       }
  2644.       RB_Remove_From_List(&unsorted_headers, bigger_header);
  2645.       RB_Insert_In_List(&first_header, bigger_header);
  2646.     }
  2647.     RB_Insert_In_List(&first_header, unsorted_headers);
  2648.   }
  2649. }
  2650.  
  2651. /*** RB_Slow_Sort ***/
  2652.  
  2653.  
  2654. /****** RoboDoc.c/RB_Insert_In_List [2.0]
  2655.  * NAME
  2656.  *   RB_Insert_In_List -- Insert a header in a list.
  2657.  * SYNOPSIS
  2658.  *   RB_Insert_In_List (anchor,new_header)
  2659.  *
  2660.  *   RB_Insert_In_List (struct RB_header **, struct RB_header *)
  2661.  * FUNCTION
  2662.  *   Insert a node in a doubly linked list.
  2663.  * INPUTS
  2664.  *   anchor     - pointer to the first node in the list.
  2665.  *   new_header - node to be inserted.
  2666.  * MODIFICATION HISTORY
  2667.  *   8. August 1995      --  optimized by koessi
  2668.  * SOURCE
  2669.  */
  2670.  
  2671. void RB_Insert_In_List(struct RB_header **anchor,
  2672.                        struct RB_header *new_header)
  2673. {
  2674.   struct RB_header *old_header;
  2675.  
  2676.   if ((old_header = *anchor) != NULL)  old_header->prev_header = new_header;
  2677.   new_header->next_header = old_header;
  2678.   new_header->prev_header = NULL;
  2679.   *anchor = new_header;
  2680. }
  2681.  
  2682. /*** RB_Insert_In_List ***/
  2683.  
  2684.  
  2685. /****** RoboDoc.c/RB_Remove_From_List [2.0]
  2686.  * NAME
  2687.  *   RB_Remove_From_List -- remove a header from a list.
  2688.  * SYNOPSIS
  2689.  *   RB_Remove_From_List (anchor, old_header)
  2690.  *   RB_Remove_From_List (struct RB_header **, struct RB_header *)
  2691.  * MODIFICATION HISTORY
  2692.  *   8. August 1995      --  optimized by koessi
  2693.  * SOURCE
  2694.  */
  2695.  
  2696. void RB_Remove_From_List(struct RB_header **anchor,
  2697.                          struct RB_header *old_header)
  2698. {
  2699.   struct RB_header *next_header = old_header->next_header;
  2700.   struct RB_header *prev_header = old_header->prev_header;
  2701.  
  2702.   if (next_header) next_header->prev_header = prev_header;
  2703.   if (prev_header) prev_header->next_header = next_header;
  2704.   else  *anchor = next_header;
  2705. }
  2706.  
  2707. /*** RB_Remove_From_List ***/
  2708.  
  2709.  
  2710. /****i* RoboDoc.c/RB_Alloc_Header [2.01]
  2711.  * NAME
  2712.  *   RB_Alloc_Header            -- oop
  2713.  * SYNOPSIS
  2714.  *   struct RB_header *RB_Alloc_Header( void )
  2715.  * FUNCTION
  2716.  *   allocate the struct RB_header
  2717.  * RESULT
  2718.  *   struct RB_header *      -- all attributes/pointers set to zero
  2719.  * AUTHOR
  2720.  *   Koessi
  2721.  * SEE ALSO
  2722.  *   RB_Free_Header()
  2723.  * SOURCE
  2724.  */
  2725.  
  2726. struct RB_header *RB_Alloc_Header(void)
  2727. {
  2728.   struct RB_header *new_header;
  2729.  
  2730.   if ((new_header = (struct RB_header *)malloc(sizeof(struct RB_header))) != NULL)
  2731.     memset(new_header, 0, sizeof(struct RB_header));
  2732.   else RB_Panic("out of memory! [Alloc Header]\n");
  2733.   return(new_header);
  2734. }
  2735.  
  2736. /*** RB_Alloc_Header ***/
  2737.  
  2738.  
  2739. /****i* RoboDoc.c/RB_Free_Header [2.01]
  2740.  * NAME
  2741.  *   RB_Free_Header             -- oop
  2742.  * SYNOPSIS
  2743.  *   void RB_Free_Header( struct RB_header *header )
  2744.  * FUNCTION
  2745.  *   free struct RB_header and associated strings
  2746.  * INPUTS
  2747.  *   struct RB_header *header -- this one
  2748.  * AUTHOR
  2749.  *   Koessi
  2750.  * SEE ALSO
  2751.  *   RB_Alloc_Header(), RB_Close_The_Shop()
  2752.  * SOURCE
  2753.  */
  2754.  
  2755. void RB_Free_Header(struct RB_header *header)
  2756. {
  2757.   if (header)
  2758.   {
  2759.     if (header->version)  free(header->version);
  2760.     if (header->name)     free(header->name);
  2761.     if (header->contents) free(header->contents);
  2762.     free(header);
  2763.   }
  2764. }
  2765.  
  2766. /*** RB_Free_Header ***/
  2767.  
  2768.  
  2769. /****i* RoboDoc.c/RB_Alloc_Link [2.01]
  2770.  * NAME
  2771.  *   RB_Alloc_Link              -- oop
  2772.  * SYNOPSIS
  2773.  *   struct RB_link *RB_Alloc_Link( char *label_name, char *file_name )
  2774.  * FUNCTION
  2775.  *   allocate struct + strings
  2776.  * INPUTS
  2777.  *   char *label_name -- strings to copy into the link
  2778.  *   char *file_name
  2779.  * RESULT
  2780.  *   struct RB_link *  -- ready-to-use
  2781.  * AUTHOR
  2782.  *   Koessi
  2783.  * SEE ALSO
  2784.  *   RB_StrDup(), RB_Free_Link()
  2785.  * SOURCE
  2786.  */
  2787.  
  2788. struct RB_link *RB_Alloc_Link(char *label_name, char *file_name)
  2789. {
  2790.   struct RB_link *new_link;
  2791.   if ((new_link = (struct RB_link *)malloc(sizeof(struct RB_link))) != NULL)
  2792.   {
  2793.     memset(new_link, 0, sizeof(struct RB_link));
  2794.  
  2795.     if (file_name) new_link->file_name = RB_StrDup(file_name);
  2796.     if (label_name) new_link->label_name = RB_StrDup(label_name);
  2797.   }
  2798.   else RB_Panic("out of memory! [Alloc Link]\n");
  2799.  
  2800.   return(new_link);
  2801. }
  2802.  
  2803. /*** RB_Alloc_Link ***/
  2804.  
  2805.  
  2806. /****i* RoboDoc.c/RB_Free_Link [2.01]
  2807.  * NAME
  2808.  *   RB_Free_Link               -- oop
  2809.  * SYNOPSIS
  2810.  *   void RB_Free_Link( struct RB_link *link )
  2811.  * FUNCTION
  2812.  *   free struct + strings
  2813.  * INPUTS
  2814.  *   struct RB_link *link
  2815.  * AUTHOR
  2816.  *   Koessi
  2817.  * SEE ALSO
  2818.  *   RB_Alloc_Link(), RB_Close_The_Shop()
  2819.  * SOURCE
  2820.  */
  2821.  
  2822. void RB_Free_Link(struct RB_link *link)
  2823. {
  2824.   if (link)
  2825.   {
  2826.     if (link->label_name) free(link->label_name);
  2827.     if (link->file_name)  free(link->file_name);
  2828.     free(link);
  2829.   }
  2830. }
  2831.  
  2832. /*** RB_Free_Link ***/
  2833.  
  2834.  
  2835. /****i* RoboDoc.c/RB_WordLen [2.01]
  2836.  * NAME
  2837.  *   RB_WordLen -- like strlen
  2838.  * SYNOPSIS
  2839.  *   int RB_WordLen( char *str )
  2840.  * FUNCTION
  2841.  *   get the amount of bytes until next space
  2842.  * INPUTS
  2843.  *   char *str -- the word
  2844.  * RESULT
  2845.  *   int -- length of the next word or 0
  2846.  * AUTHOR
  2847.  *   Koessi
  2848.  * SEE ALSO
  2849.  *   RB_Find_Header_Name()
  2850.  * SOURCE
  2851.  */
  2852.  
  2853. int RB_WordLen(char *str)
  2854. {
  2855.   int   len;
  2856.   char  c;
  2857.   for (len = 0; ((c = *str) != '\0') && !isspace(c) && (c != '\n'); ++str, ++len)
  2858.     ;
  2859.   return(len);
  2860. }
  2861.  
  2862. /*** RB_WordLen ***/
  2863.  
  2864.  
  2865. /****i* RoboDoc.c/RB_StrDup [2.01]
  2866.  * NAME
  2867.  *   RB_StrDup
  2868.  * SYNOPSIS
  2869.  *   char *RB_StrDup( char *str )
  2870.  * FUNCTION
  2871.  *   duplicate the given string
  2872.  * INPUTS
  2873.  *   char *str               -- source
  2874.  * RESULT
  2875.  *   char *                  -- destination
  2876.  * AUTHOR
  2877.  *   Koessi
  2878.  * SOURCE
  2879.  */
  2880.  
  2881. char *RB_StrDup(char *str)
  2882. {
  2883.   char *dupstr;
  2884.   if ((dupstr = (char *)malloc((strlen(str) + 1) * sizeof(char))) != NULL)
  2885.       strcpy(dupstr, str);
  2886.   else RB_Panic("out of memory! [StrDup]\n");
  2887.   return(dupstr);
  2888. }
  2889.  
  2890. /*** RB_StrDup ***/
  2891.  
  2892.  
  2893. /****i* RoboDoc.c/RB_CookStr [3.0h]
  2894.  * NAME
  2895.  *   RB_CookStr
  2896.  * SYNOPSIS
  2897.  *   char *RB_CookStr( char *str )
  2898.  * FUNCTION
  2899.  *   duplicate the given string, massaging it for the current output_mode
  2900.  * INPUTS
  2901.  *   char *str               -- source
  2902.  * RESULT
  2903.  *   char *                  -- destination
  2904.  * AUTHOR
  2905.  *   apang
  2906.  * NOTES
  2907.  *   Doesn't try/need to be as aggressive as RB_Generate_Item_Body()
  2908.  ****/
  2909.  
  2910. char *RB_CookStr(char *str)
  2911. {
  2912.   static char work_buf[MAX_LINE_LEN];
  2913.   char *cptr, c;
  2914.   int i;
  2915.  
  2916.   cptr = work_buf;
  2917.   switch (output_mode) {
  2918.     case LATEX:
  2919.       for (i = 0; ((c = *str++) != '\0') && (i < (MAX_LINE_LEN - 1)); ) {
  2920.         i++;
  2921.         if (c == '_') {
  2922.           if (i < (MAX_LINE_LEN - 1)) {
  2923.             *cptr++ = '\\'; *cptr++ = '_';
  2924.             i++;
  2925.           } else {
  2926.             break;
  2927.           }
  2928.         } else {
  2929.           *cptr++ = c;
  2930.         }
  2931.       }
  2932.       break;
  2933.  
  2934.     case RTF:
  2935.       for (; (c = *str++) != '\0'; ) {
  2936.         if (isalnum(c) || c == '.' || c == '_') {
  2937.           *cptr++ = c;
  2938.         }
  2939.       }
  2940.       break;
  2941.  
  2942.     default:
  2943.       return RB_StrDup(str);
  2944.   }
  2945.  
  2946.   *cptr = '\0';
  2947.   return RB_StrDup(work_buf);
  2948. }
  2949.  
  2950. /*** RB_CookStr ***/
  2951.  
  2952.  
  2953. /****i* RoboDoc.c/RB_Say [2.01]
  2954.  * NAME
  2955.  *   RB_Say                     -- varargs
  2956.  * SYNOPSIS
  2957.  *   void RB_Say( char *what, char *why, ... )
  2958.  * FUNCTION
  2959.  *   say what's going on
  2960.  * INPUTS
  2961.  *   char *format            -- formatstring
  2962.  *    ...                    -- parameters
  2963.  * AUTHOR
  2964.  *   Koessi
  2965.  * SOURCE
  2966.  */
  2967.  
  2968. void RB_Say(char *format, ...)
  2969. {
  2970.   va_list  ap;
  2971.   if (course_of_action & DO_TELL)
  2972.   {
  2973.     va_start(ap, format);
  2974.     printf("%s: ", whoami);
  2975.     vprintf(format, ap);
  2976.     va_end(ap);
  2977.   }
  2978. }
  2979.  
  2980. /*** RB_Say ***/
  2981.  
  2982.  
  2983. /****i* RoboDoc.c/RB_Panic [2.01]
  2984.  * NAME
  2985.  *   RB_Panic -- free resources and shut down
  2986.  * SYNOPSIS
  2987.  *   void RB_Panic( char *format, char *why, ... )
  2988.  * FUNCTION
  2989.  *   Print error message.
  2990.  *   Frees all resources used by robodoc.
  2991.  *   Terminates program
  2992.  * INPUTS
  2993.  *   char *format            -- formatstring
  2994.  *   ...                     -- parameters
  2995.  * AUTHOR
  2996.  *   Koessi
  2997.  * SOURCE
  2998.  */
  2999.  
  3000. void RB_Panic(char *format, ...)
  3001. {
  3002.   va_list  ap;
  3003.   va_start(ap, format);
  3004.   printf("%s: FATAL ERROR - ", whoami);
  3005.   vprintf(format, ap);
  3006.   printf("%s: closing down...\n", whoami);
  3007.   va_end(ap);
  3008.   RB_Close_The_Shop();
  3009.   exit(RB_RETURN_PANIC);  /* 20..100 */
  3010. }
  3011.  
  3012. /*** RB_Panic ***/
  3013.  
  3014.  
  3015. /****i* RoboDoc.c/RB_Close_The_Shop [3.0b]
  3016.  * NAME
  3017.  *   RB_Close_The_Shop -- free resources.
  3018.  * SYNOPSIS
  3019.  *   void RB_Close_The_Shop ()
  3020.  * FUNCTION
  3021.  *   Frees all resources used by robodoc.
  3022.  * BUGS
  3023.  *   Did free cur_header after advancing (zzzzz)
  3024.  * SEE ALSO
  3025.  *   RB_Free_Header(), RB_Free_Link()
  3026.  * SOURCE
  3027.  */
  3028.  
  3029. void RB_Close_The_Shop()
  3030. {
  3031.   struct RB_header  *cur_header, *tmp_header;
  3032.   struct RB_link    *cur_link,   *tmp_link;
  3033.  
  3034.   if (document)        fclose(document);
  3035.   if (dest_doc)        fclose(dest_doc);
  3036.   if (xreffiles_file)  fclose(xreffiles_file);
  3037.   if (xref_file)       fclose(xref_file);
  3038.  
  3039.   for (cur_header = first_header; cur_header; )
  3040.   {
  3041.     tmp_header = cur_header->next_header;
  3042.     RB_Free_Header(cur_header);
  3043.     cur_header = tmp_header;
  3044.   }
  3045.  
  3046.   for (cur_link = first_link; cur_link; )
  3047.   {
  3048.     tmp_link = cur_link->next_link;
  3049.     RB_Free_Link(cur_link);
  3050.     cur_link = tmp_link;
  3051.   }
  3052.  
  3053.   if (header_index)  free(header_index) ;
  3054.   if (link_index)    free(link_index) ;
  3055. }
  3056.  
  3057. /*** RB_Close_The_Shop ***/
  3058.